品質と提供SLA|データエンジニアリング実践
このページはプロモーション(広告)を含みます。
データエンジニアリング実践(上級・読む35分+演習45分)
この授業のゴール
- SLI・SLO・SLAの違いを説明し、鮮度・完全性・正確さの指標を、測り方(分母・時点)まで含めて書ける
- 照合と契約検査の結果から、提供・注記つき提供・保留の判定を閾値で自動化できる
- 1か月の提供記録から達成率とエラー予算の残りを計算し、パーセントとパーセントポイントを区別して報告できる
- 利用者との提供SLAに、対象・指標・目標・測定方法・除外・違反時の対応を具体的な値で書ける
仕事でどう使うか
ここまでの授業で、契約で入口を守り(L01)、変更と時刻を正しく扱い(L02)、枠を確定し(L03)、照合と再処理で訂正できる(L04)ようになりました。残る問いは「今日の数字を、利用者に出してよいか」と「どのくらいの品質を約束できるか」です。これを数値で決めて記録するのが、この授業の内容です。
| 路線 | この授業が使われる成果物・意思決定 |
|---|---|
| DS(データサイエンティスト) | 分析に使う表の鮮度と完全性を確認し、条件を満たさない日は報告書に注記する |
| ML(機械学習エンジニア) | 学習・推論に使う特徴量の品質ゲートを置き、条件を満たさない日はモデルの更新を止める |
| DX(DX推進・AI企画) | 業務部門とデータ提供の約束(SLA)を結び、毎月の達成状況を報告して改善の優先順位を決める |
| RS(研究者) | 計測データの欠落率・遅延を記録し、解析から除外する基準を事前に決めておく |
品質の約束は「速いほどよい」「完璧であるべき」ではありません。利用者の意思決定に必要な水準を数値で決め、それを守るための運用費と釣り合わせます。
前提
次の言葉を使います。不安があれば先に戻ってください。
- 受入基準と品質の検査 → 「受入基準」(有料版)、「整合性と分布変化」(有料版)
- 鮮度とアクセス制御 → 「鮮度とアクセス制御」(有料版)
- SLOとユーザー影響 → 「SLOとユーザー影響」(有料版)、監視と通知 → 「監視と通知」(有料版)
- 照合(missing・mismatch)と版 → 整合性と再処理、契約違反の隔離 → 取込契約と粒度
割合(0〜1の値)とパーセント(割合×100)、2つのパーセントの差を表すパーセントポイント(pt)を区別します。95%から97%への変化は「2pt上昇」で、「2%上昇」(95%×1.02=96.9%)とは違います。
身近な状況:「毎朝9時までに出す」と約束したら、何を測るか
販促部と経理に、前日の日次売上表を毎朝提供しています。ある月の終わりに、次の3つの声が届きました。
| 誰が | 声 |
|---|---|
| 販促部 | 「たまに9時に間に合わない。平均は8時50分だと言われたが、遅い日に限って会議がある」 |
| 経理 | 「18日の数字は1.8%少なかった。翌日に直っていたが、その間に部長へ報告してしまった」 |
| データ基盤の担当 | 「処理はすべて成功している。何が悪いのかわからない」 |
担当者の言う「成功」は、処理がエラーなく終わったことです。利用者が気にしているのは、(1) 期限に間に合ったか(鮮度)、(2) 欠けていないか(完全性)、(3) 正しいか(正確さ)です。処理の成功と、利用者にとっての品質は別物です。
この授業では、利用者が気にしている品質を指標にし、目標を決め、目標を満たさない日は数字を出さずに前回版を「前回版」と明示して表示する提供判定を作ります。さらに、利用者との約束(SLA)として文書にします。
直感的な説明:宅配便の「お届け予定」と「お届け率」
宅配便にたとえます。
- SLI(測るもの):その日の荷物が、予定時刻までに届いたか。荷物が全部そろっていたか。
- SLO(社内の目標):「月の95%以上の日で、予定時刻までに全部届ける」。
- SLA(お客さまとの約束):「予定時刻に遅れたら連絡する。月の達成率が90%を下回ったら原因と対策を報告する」。違反したときにどうするかまで含みます。
- エラー予算:目標95%なら、30日のうち1.5日ぶんは遅れてもよい「余裕」があります。余裕を使い切りそうなら、新しい配送ルートの試行(新機能の追加)を止めて、確実に届ける改善を優先します。
- 提供判定:荷物が一部壊れていたら、そのまま届けずに「お届けを保留し、連絡する」。
ポイントは、SLO を SLA より厳しくすることです。社内の目標(95%)を少し厳しめに置き、お客さまとの約束(90%)には余裕を残しておくと、約束を破る前に気づいて直せます。
たとえ話の限界:宅配便の遅れは目で見えますが、データの欠けは見えません。1.8%欠けた売上表も、見た目は普通の表です。だからこそ、照合の結果を使って機械的に判定します。
正確な定義:SLI・SLO・SLA・エラー予算・提供判定
SLI(Service Level Indicator:サービスレベル指標):利用者が感じる品質を数値にしたもの。データ提供では次の3つが基本です。
| 指標 | 定義(日次の売上表の例) | 正の値(分母)の取り方 |
|---|---|---|
| 鮮度 | 前日分の確定版が、期限(9:00)までに提供されたか(日ごとに達成/未達) | 提供時刻は「処理の終了」ではなく「判定に合格して利用者が見られるようになった時刻」 |
| 完全性 | 提供件数 ÷ 正の件数 | 業務システムの確定記録や、送信側が通知する件数(制御合計) |
| 正確さ | $\lvert \text{提供金額} - \text{正の金額} \rvert \div \text{正の金額}$ | 同上 |
ストリームの場合の鮮度は「確認した時刻 − 提供済みの最新の確定枠の終わり」(分)のように、遅れの長さで測ります(バッチとストリーム)。
SLO(Service Level Objective:サービスレベル目標):SLI の目標と、測る期間。例:「30日間で、鮮度を満たす日の割合が95%以上」。
SLA(Service Level Agreement:サービスレベル合意):利用者との約束。SLO より緩い目標と、違反時の対応(連絡・報告・補償など)を含みます。契約上の補償を伴う SLA の扱いは組織や契約で異なります(執筆時点(2026年)の一般的な説明。実際の契約は法務・調達の担当と確認)。
エラー予算:期間中に許される未達の量。
$$\text{エラー予算} = (1 - \text{SLO}) \times \text{期間の日数}$$
記号の意味:SLO は目標の割合(0〜1、単位なし)、期間の日数の単位は日。SLO=0.95、30日なら $(1 - 0.95) \times 30 = 1.5$ 日です。未達が1日なら残り0.5日、2日なら残り $-0.5$ 日(超過)です。
達成率:$\text{期限内の日数} \div \text{全日数}$。未提供(保留して前回版を出した日)は未達に数えます。
提供判定(品質ゲート):区画ごとに次の3値で判定します。この授業で使う閾値は架空の例です。
| 判定 | 条件(いずれか1つでも当てはまれば) | 利用者に見えるもの |
|---|---|---|
| hold(保留) | 件数の差 > 1%、金額の差 > 0.5%、隔離率 > 2% | 前回版を「前回版・○日分は確認中」と明示して表示 |
| note(注記つき提供) | 件数の差 > 0.1%、金額の差 > 0.1%、隔離率 > 0.5% | 今回の版を「暫定・差○%」と注記して表示 |
| publish(提供) | 上のどれにも当てはまらない | 今回の版 |
件数・金額の差は $\lvert \text{提供} - \text{正} \rvert \div \text{正}$ で測ります。絶対値なので、欠け(少ない)も二重計上(多い)も同じように捕まえます。隔離率は契約違反で隔離した行 ÷ 受信した行です(取込契約と粒度)。
段階付き例題:18日の判定と、月の達成率
入力:18日の照合結果は、正の件数1,000件・金額520,000円、提供側982件・510,640円。受信1,010件のうち隔離0件。
ステップ1:差を計算。件数の差 $\lvert 982 - 1000 \rvert \div 1000 = 0.018$(1.8%)。金額の差 $\lvert 510640 - 520000 \rvert \div 520000 = 9360 \div 520000 = 0.018$(1.8%)。
ステップ2:判定。件数の差1.8% > 1% なので hold。利用者には17日までの前回版を「18日分は確認中」と表示し、担当者に通知します。経理が欠けた数字を部長に報告する事故はこれで防げます。
ステップ3:月の記録。この月は、7日に上流の遅れで9:20提供、18日は保留で未提供(翌日に再処理して提供)、他の28日は9:00までに提供でした。
ステップ4:達成率とエラー予算。達成率 $28 \div 30 = 0.933$(93.3%)。SLO 95% に対して 1.7pt 不足です。エラー予算は1.5日、使ったのは2日なので、残りは $1.5 - 2 = -0.5$ 日(超過)。
ステップ5:意味。予算を超過したので、来月は新しいデータ源の追加を後回しにし、7日の遅れ(上流)と18日の欠け(原因の調査)への対策を優先する、という判断の根拠になります。
def gap(served, expected):
"""提供値と正の値の差の割合(両方0なら0、正が0で提供が正なら無限大)"""
if expected == 0:
return 0.0 if served == 0 else float("inf")
return abs(served - expected) / expected
def gate(c):
"""提供判定。'publish'(提供)・'note'(注記つき提供)・'hold'(保留して前回版を表示)を返す"""
n_gap = gap(c["served_n"], c["expected_n"])
t_gap = gap(c["served_total"], c["expected_total"])
q_rate = c["quarantined"] / c["received"] if c["received"] else 0.0
if n_gap > 0.01 or t_gap > 0.005 or q_rate > 0.02:
return "hold"
if n_gap > 0.001 or t_gap > 0.001 or q_rate > 0.005:
return "note"
return "publish"
def slo_report(records, deadline="09:00", target=0.95):
"""日ごとの提供時刻から、期限内の提供率とエラー予算の残りを計算する"""
n = len(records)
met = sum(1 for r in records if r["published_at"] is not None and r["published_at"] <= deadline)
budget = (1 - target) * n
return {"days": n, "met": met, "rate": met / n if n else 1.0,
"budget": budget, "used": n - met, "left": budget - (n - met)}
day18 = dict(expected_n=1000, served_n=982, expected_total=520000, served_total=510640, received=1010, quarantined=0)
print("18日の判定:", gate(day18))
times = ["08:40"] * 30
times[6] = "09:20" # 7日:上流の遅れ
times[17] = None # 18日:保留(未提供)
records = [{"day": d + 1, "published_at": t} for d, t in enumerate(times)]
r = slo_report(records)
print(f"達成率 {r['rate']:.1%}({r['met']}/{r['days']}日)")
print(f"エラー予算 {r['budget']:.1f}日、使用 {r['used']}日、残り {r['left']:.1f}日")
print(f"SLOとの差 {(r['rate'] - 0.95) * 100:+.1f}pt")
関数の説明:gap(served, expected) は差の割合(float)を返します。gate(c) は照合結果の辞書 c を受け取り、'publish'・'note'・'hold' のいずれか(str)を返します。slo_report(records, deadline, target) は日ごとの提供時刻('HH:MM' の文字列、未提供は None)のリストから、日数・期限内の日数・達成率・エラー予算・使用・残りの辞書を返します。
操作して理解する:平均では見えない遅れと、閾値の効き方
鮮度を「平均の遅れ」で測ると何が起きるかを確かめます。下は、ある月の30日分の「日次処理の開始(8:00)から提供までの所要時間」(分)です。60分以内なら 9:00 の期限に間に合います。
lags = [40] * 28 + [180, 200] # 28日は40分、2日だけ3時間以上かかった
mean = sum(lags) / len(lags)
within = sum(1 for x in lags if x <= 60) / len(lags)
print(f"平均 {mean:.0f}分(目標60分以内なら「達成」に見える)")
print(f"60分以内に提供できた日の割合 {within:.1%}")
print("最も遅い2日:", sorted(lags)[-2:], "分")
平均は50分で目標60分を下回りますが、60分以内に間に合った日は93.3%しかありません。利用者が困るのは「遅い日」なので、SLO は平均ではなく割合(または95パーセンタイルのような上位の値)で書きます。
次に、提供判定の閾値を変えて考えてみましょう(本文の例題の gate を使います)。
- 18日の提供側が 995件・517,400円 なら? → 件数の差0.5%、金額の差0.5% なので hold の閾値(1%・0.5%)を超えず、note になります。
- 二重計上で 1,020件・530,400円 なら? → 件数の差2%で hold。差を絶対値で測るので、多すぎる場合も捕まります。
- hold の閾値を「件数の差 > 5%」に緩めると、18日の1.8%の欠けは note として提供されます。経理がそれを見て報告したら? 閾値は「利用者がその差で判断を誤るか」で決め、利用者と合意します。
注意:閾値を厳しくするほど hold が増え、鮮度の SLO を食いつぶします。品質の SLO と鮮度の SLO は引っ張り合う関係です。両方を同時に満たせないときにどちらを優先するか(経理なら正確さ、販促の速報なら鮮度)を、SLA に書いておきます。
発展:SLAの書き方、除外、測定そのものの品質
SLA の項目(日次売上表の例。数値は架空)
| 項目 | 例 |
|---|---|
| 対象 | 日次売上表(売上日ごと、税抜、取消・返金を除く確定値) |
| 指標と目標 | 鮮度:前日分を 9:00 までに提供する日が月90%以上。正確さ:業務システムとの金額の差0.5%以内 |
| 測定方法 | 提供判定の合格時刻を記録。照合は業務システムの確定記録と日ごとに実施 |
| 除外 | 事前に通知した計画停止、業務システム側の障害で正のデータが届かない日 |
| 違反時の対応 | 9:00 に間に合わない場合は 8:45 までに見込み時刻を連絡。月の目標を下回ったら翌月5営業日以内に原因と対策を報告 |
| 訂正の通知 | 確定値を版2以降に訂正したら、差と理由を当日中に通知(整合性と再処理) |
| 連絡先と責任者 | データ基盤担当(一次)、データ基盤責任者(エスカレーション) |
除外を広げすぎない:除外が多い SLA は、数字上は達成していても利用者の不満を減らしません。除外した日数も一緒に報告します。
測定の品質:SLI を測る仕組み自体が止まると、「未達がない」ように見えます。提供判定のログが1日分欠けたら「未達」として数える(記録がない=確認できない)規則にしておくと、測定の停止を見逃しません。
SLO を100%にしない:100%は1日の未達も許さないので、エラー予算がゼロになり、改善のための変更(新しいデータ源の追加、規則の修正)が一切できなくなります。また上流の業務システムが100%でない限り、達成もできません。
限界:照合の「正」が当日中に確定しないデータ(返品が数日後に確定する売上など)では、当日の完全性は測れません。その場合は「暫定の完全性」(送信側の制御合計との比較)と「確定後の完全性」(数日後の照合)を分けて SLI にします。
よくある失敗
失敗1:処理の終了時刻で鮮度を測り、古いデータを「新鮮」と報告する
# 処理は毎朝 8:30 に終わっている。しかし上流が止まり、データは3日前のまま
jobs = [{"day": "05-10", "finished": "08:30", "latest_data_day": "05-07"}]
for j in jobs:
print("処理の終了で測ると:", "達成" if j["finished"] <= "09:00" else "未達")
print("データの日付で測ると:", "達成" if j["latest_data_day"] == "05-09" else "未達",
f"(前日 05-09 のはずが {j['latest_data_day']})")
処理が毎日成功していても、上流からデータが届いていなければ、同じ古い数字を毎日作り直しているだけです。直し方:鮮度は「提供しているデータの中身がいつの分か」(最新の確定区画、最大のイベント時刻)で測る。処理の成功・失敗は運用の監視(「監視と通知」(有料版))で別に見る。
失敗2:平均で SLO を書き、遅い日を見逃す
「平均の提供時刻が 9:00 より前」という SLO は、本文の例のように平均50分でも、2日は3時間以上遅れていることを隠します。利用者が困るのはその2日です。
lags = [40] * 28 + [180, 200]
print("平均:", sum(lags) / len(lags), "分")
print("95パーセンタイル(上から2番目付近):", sorted(lags)[int(0.95 * len(lags))], "分")
95パーセンタイル(小さい順に並べて95%の位置の値)は180分で、遅い日の存在がはっきり出ます。直し方:「期限内の日の割合が95%以上」または「95パーセンタイルの遅れが60分以内」のように、遅い側を測る指標で書く。
失敗3:完全性の分母を自分の取込件数にする
source_sent = 1000 # 送信側が通知した件数(制御合計)
ingested = 982 # 取り込めた件数(18件は通信断で届いていない)
served = 982
print("自分の取込件数を分母にすると:", f"{served / ingested:.1%}")
print("送信側の件数を分母にすると:", f"{served / source_sent:.1%}")
自分が受け取った件数を分母にすると、届かなかった行は分母からも消えるので、完全性はいつも100%になります。直し方:分母は基盤の外から取る。業務システムの確定記録、または送信側がファイルやメッセージと一緒に送る件数・金額(制御合計)を契約に入れる(取込契約と粒度)。
失敗4:パーセントとパーセントポイントを混同して報告する
先月の達成率93.3%、今月96.7%。「達成率が3.4%改善」と報告すると、読み手は $93.3 \times 1.034 = 96.5\%$ になったと読むかもしれません。
| 表現 | 意味 | この例 |
|---|---|---|
| パーセントポイント(pt) | 2つの%の差 | $96.7 - 93.3 = 3.4$ pt |
| 相対変化(%) | 前の値に対する比 | $(96.7 - 93.3) \div 93.3 = 3.6\%$ |
直し方:達成率・完全性・隔離率の変化は「3.4pt 改善」と書く。相対変化を使うときは「前月比」と明記する。未達の日数(2日→1日)を併記すると、利用者は実感をつかみやすくなります。
まとめ
- SLI は利用者が感じる品質の測定値、SLO は社内目標、SLA は違反時の対応を含む利用者との約束。SLO を SLA より厳しく置く。
- 鮮度はデータの中身の時点、完全性・正確さは基盤の外の正(確定記録・制御合計)を分母にして測る。
- 提供判定は差を絶対値で測り、hold・note・publish を閾値で自動化する。保留した日は未達に数える。
- エラー予算=(1−SLO)×期間。使い切りそうなら変更を止めて改善を優先する判断材料にする。
- SLO は平均でなく割合や上位パーセンタイルで書き、変化はパーセントポイントで報告する。
用語
- SLI(サービスレベル指標)(Service Level Indicator)
利用者が感じる品質(鮮度・完全性・正確さなど)を数値にしたもの。
- SLO(サービスレベル目標)(Service Level Objective)
SLI の目標値と測る期間。例:30日間で期限内提供の日の割合95%以上。
- SLA(サービスレベル合意)(Service Level Agreement)
利用者との品質の約束。SLO より緩い目標と、違反時の連絡・報告などの対応を含む。
- エラー予算(error budget)
期間中に許される未達の量。(1−SLO)×期間で計算する。
- 提供判定(品質ゲート)(quality gate)
照合や契約検査の結果から、区画ごとに提供・注記つき提供・保留を決める仕組み。
- 制御合計(control total)
送信側がデータと一緒に通知する件数や金額の合計。受信側の完全性を確かめる分母に使う。
よくある質問
なぜ「処理の成功」だけを監視するのでは足りないのですか?
処理が成功しても、上流のデータが古い・欠けている・二重になっていることがあります。利用者が困るのは数字の鮮度・完全性・正確さなので、それを直接測る SLI が必要です。処理の成功・失敗は運用の監視(「監視と通知」(有料版))として別に見ます。
SLO と KPI(Key Performance Indicator:重要業績評価指標)はどう違いますか?
KPI は事業の成果(売上、解約率など)を測る指標で、SLO はサービスの品質(データが期限内に正しく届くか)の目標です。SLO を守ることは、KPI を正しく測るための前提条件です。
hold(保留)にすると鮮度の SLO を落とします。それでも保留すべきですか?
利用者がその差で判断を誤るなら保留すべきです。間違った数字で意思決定するほうが、1日遅れるより損失が大きいことが多いからです。ただし用途で変わります。販促の速報は鮮度優先で note として出し、経理の確定値は正確さ優先で hold にする、のように利用者ごとに決めて SLA に書きます。
閾値(1%、0.5%など)はどう決めればよいですか?
まず過去の照合結果の差の分布を見ます。普段の差が0.05%程度なら、0.1%を超えたら注記、という値に意味があります。次に、利用者に「何%ずれたら判断が変わるか」を聞きます。最後に、hold が月に何回起きるかを過去データで試算し、鮮度の SLO と両立するかを確かめます。
エラー予算を使い切ったら、何をするのですか?
多くの組織では、新しいデータ源の追加や大きな変更を一時的に止め、未達の原因対策(上流との遅延の取り決め、再処理の自動化など)を優先します。予算が余っているときは、変更を進めてよい根拠になります。事前に「予算を超えたらどうするか」を合意しておくのがポイントです。
正のデータが数日後にしか確定しない場合は、どうしますか?
当日は送信側の制御合計で「暫定の完全性」を測って note つきで提供し、正が確定した時点で照合して版を上げます(整合性と再処理)。SLA には「暫定値と確定値がある」「確定はいつか」を明記します。
確認問題
問1 SLI・SLO・SLA の関係として最も適切なものはどれか。
- ① SLI は利用者との約束、SLO は測った値、SLA は社内目標
- ② SLI は測る指標、SLO はその社内目標、SLA は違反時の対応を含む利用者との約束で、ふつう SLO より緩くする
- ③ 3つは同じ意味で、組織によって呼び方が違うだけ
- ④ SLA は SLO より厳しく置き、社内目標には余裕を持たせる
解答と解説
正解:②
SLI を測り、SLO で社内の目標を置き、SLA で利用者と約束します。SLO を厳しめにしておくと、SLA を破る前に気づけます。
問2 30日間の SLO が「期限内に提供した日の割合95%以上」のとき、エラー予算は何日か。
- ① 1.5日
- ② 0.95日
- ③ 5日
- ④ 28.5日
解答と解説
正解:①
(1 − 0.95) × 30 = 1.5日です。
問3 毎朝の処理はすべて 8:30 に成功している。しかし上流が止まり、提供している最新の区画は3日前のままだった。鮮度の SLI の判定として正しいものはどれか。
- ① 処理が成功しているので達成
- ② 提供しているデータの中身が前日分でないので未達
- ③ 上流の障害なので測定の対象外として達成
- ④ 処理時刻が 9:00 より前なので達成
解答と解説
正解:②
鮮度はデータの中身がいつの分かで測ります。処理の成功は利用者にとっての品質ではありません。
問4 照合で、正の件数1,000件に対して提供側が1,020件だった(金額も2%多い)。本文の閾値で判定するとどれか。
- ① publish(多い分には問題ない)
- ② note(注記つき提供)
- ③ hold(保留して前回版を表示)
- ④ 判定できない
解答と解説
正解:③
差は絶対値で測るので、2%の二重計上は件数の閾値1%を超え、hold です。
問5 先月の達成率が93.3%、今月が96.7%だった。最も正確な報告はどれか。
- ① 達成率が3.4%改善した
- ② 達成率が3.4pt改善した(未達の日は2日から1日へ)
- ③ 達成率が103.6%になった
- ④ 達成率の変化は報告しなくてよい
解答と解説
正解:②
2つのパーセントの差はパーセントポイントで表します。日数を併記すると実感がつかめます。
問6 完全性の SLI の分母として最も適切なものはどれか。
- ① 基盤が取り込めた件数
- ② 前日の提供件数
- ③ 過去30日の平均件数
- ④ 業務システムの確定記録や、送信側が通知する件数(制御合計)
解答と解説
正解:④
分母は基盤の外から取ります。自分の取込件数を分母にすると、届かなかった行が分母からも消えます。
次に学ぶこと
次の 基盤設計と障害演習 では、L01〜L05 の部品(契約・CDC・watermark・再処理と版・照合・提供判定・SLO)を1つの基盤設計にまとめ、遅延・重複・処理の中断を意図的に注入する障害演習で、件数と金額が守られることを確かめます。
戻って確認するなら、SLO の考え方は 「SLOとユーザー影響」(有料版)、監視と通知は 「監視と通知」(有料版)、監査レポートは 「監査レポート」(有料版) です。
キャリア学習:データサイエンティスト・機械学習エンジニア・DX推進・研究者を目指す人の学習アプリ。164モジュール・984授業を、ブラウザで動くSQLとPythonの演習で。基礎と各分野の最初のモジュールは無料。全部は2,980円の買い切り。
アプリを無料で開く有料版と無料版の違い