🎓 レベル:標準 | 重要度:A(必須)
📎 前提:データ取り込み(バッチ・CDC) | 関連:データ品質とテスト・ワークフローオーケストレーション
要点(BLUF)
- **べき等(idempotent)**とは「同じ操作を何回実行しても、結果が1回実行したときと同じ」性質。
f(f(x)) = f(x)。 - パイプラインは必ず失敗する(ネットワーク断・タイムアウト・途中停止)。だから安全に再実行できることが前提になり、その鍵がべき等性。
- 実装の定番は UPSERT(INSERT … ON CONFLICT / MERGE) と パーティション単位の上書き(delete-insert / overwrite)。素朴な
INSERT追記は再実行で二重になり非べき等。
概念 ── なぜ再実行が前提なのか
分散・スケジュール実行では、ジョブが途中で死ぬのは日常です。リトライ(自動再実行)で回復しますが、そのとき**「もう半分書き込んでいたら?」**が問題になります。べき等なら「もう一度全部流す」だけで正しい状態に収束するので、復旧が圧倒的に楽になります。
flowchart LR
R["ジョブ失敗・途中停止"] --> RT["リトライ(再実行)"]
RT --> Q{"べき等?"}
Q -->|はい| OK["何回流しても同じ結果 -> 安全"]
Q -->|いいえ| NG["重複・二重計上 -> データ破損"]
仕組み ── 素朴INSERT vs UPSERT
同じバッチを2回流して比べます。
-- 非べき等:追記なので再実行で二重に
INSERT INTO target_naive(id,val) VALUES (1,10),(2,20),(3,30);
-- べき等:主キー衝突時は更新。何回流しても3行のまま
INSERT INTO target_upsert(id,val) VALUES (1,10),(2,20),(3,30)
ON CONFLICT(id) DO UPDATE SET val=excluded.val;
実行結果(実機・SQLite/各2回実行):
素朴INSERTを2回 -> 6 行(重複・3行のはずが倍)
UPSERTを2回 -> 3 行(べき等・3行のまま)
UPSERTは「無ければ挿入、有れば更新」。同じ鍵のデータが何度来ても、最終状態は1回流したのと同じ。これが冪等設計の最小形です。
設計の勘所 ── 冪等にする4つの型
| 手法 | やり方 | 向く場面 |
|---|---|---|
| UPSERT/MERGE | 主キー衝突で更新 | 行単位の取り込み |
| delete-insert | 対象パーティションを消してから入れ直す | 日次パーティション再生成 |
| overwrite | パーティション/テーブルを丸ごと置換 | バッチ全再計算 |
| 自然キー+去重 | 一意キーで重複排除してから書く | イベント取り込み |
ポイントは「書き込みを“追記”でなく“その鍵の最終状態への収束”にする」こと。日次バッチなら「6月3日分を再計算するなら、6月3日のパーティションを消して入れ直す」。途中で死んでも、もう一度流せば同じ6月3日分になります。Airflowの再実行(→ ワークフローオーケストレーション)が安心して使えるのは、各タスクが冪等だからです。
なぜそうするか ── exactly-once の現実解
なぜ「ちょうど1回(exactly-once)」を保証しようとしないのか。分散環境で送達を厳密に1回にするのは非常に難しい(→ 分散システム)。現実解は「at-least-once(最低1回)配送+べき等な受け手」。重複が来ることを前提に、受け手が重複を吸収すれば、実質的にexactly-onceと同じ結果になります。「壊れない配送」を作るより「壊れた配送が来ても結果が壊れない受け手」を作る方が、はるかに堅牢です。
⚠️ よくある落とし穴
- 追記
INSERTで日次集計 → 再実行のたびに二重計上。UPSERTかパーティション上書きに。 - 自動採番(AUTO INCREMENT)を鍵に使う → 再実行で別IDが振られ重複検知できない。源由来の自然キーを使う。
- 「成功したはず」を信じる → ネットワーク断で結果が返らないだけのことが多い。返事が無い=失敗扱いで再実行できる設計に。
- 外部API呼び出しが非べき等(課金・メール送信)→ 冪等キー(idempotency key)をAPIに渡す。
対応ラボ
data-engineering-study/labs/04_etl_pipeline.py(PYTHONIOENCODING=utf-8 で実行・素朴INSERT二重化とUPSERT冪等を確認済み)。
関連
- 増分取り込みと組み合わせる前提は データ取り込み(バッチ・CDC)
- 再実行を司るスケジューラは ワークフローオーケストレーション
- 結果の正しさを保証するのは データ品質とテスト