【要約】INSERT OR IGNORE が効いていなかった。5,881行のデータが95,737行になっていた [Zenn_Python] | Summary by TechDistill
> Source: Zenn_Python
Execute Primary Source
// Problem
開発者がDiscord通知保存BOTを運用中、データ件数が想定の16倍に膨らむ問題に直面した。
- 原因:
- 検知の困難さ:エラーが発生せず、行数の増加も正常な挙動に見えるため、長期間気づけなかった。
- データの歪み:再挿入のタイミングによりレコードごとに水増し率が異なり、集計の順位が狂う事態を招いた。
- 原因:
INSERT OR IGNORE を使用していたが、テーブルに UNIQUE 制約が設定されていなかった。- 検知の困難さ:エラーが発生せず、行数の増加も正常な挙動に見えるため、長期間気づけなかった。
- データの歪み:再挿入のタイミングによりレコードごとに水増し率が異なり、集計の順位が狂う事態を招いた。
// Approach
開発者は、整合性を守るため「入れない守り」と「壊れない守り」の二段構えを採用した。
- データの整理:
- スキーマ強化:
- クエリ堅牢化:集計時に
- データの整理:
MIN(id) を用いて重複レコードを削除し、クレンジングを行った。- スキーマ強化:
CREATE UNIQUE INDEX を作成し、物理的に重複の挿入を阻止した。- クエリ堅牢化:集計時に
COUNT(DISTINCT ...) を使い、重複混入時も数値が狂わないよう対策した。// Result
この対策により、データの整合性が確保され、集計結果の正確性が回復した。
- 定量的効果:95,737行あったデータが、実データである5,881行へと正しく整理された。
- 運用の改善:制約とDISTINCTを併用する理由を、数値を用いて運用メモに明文化した。
- 再発防止:将来的な仕様変更や手動投入によるデータの歪みを防ぐ体制を整えた。
- 定量的効果:95,737行あったデータが、実データである5,881行へと正しく整理された。
- 運用の改善:制約とDISTINCTを併用する理由を、数値を用いて運用メモに明文化した。
- 再発防止:将来的な仕様変更や手動投入によるデータの歪みを防ぐ体制を整えた。
Senior Engineer Insight
> DB設計における制約の重要性を再認識させる事例だ。制約は「入り口」を守るが、運用が進むと入り口は増え続ける。そのため、集計クエリ側でも
DISTINCT を用いる「防御的プログラミング」が不可欠だ。また、後続の作業者が「冗長なコード」と誤解して削除しないよう、数値を用いた具体的な理由をドキュメントに残す姿勢は、大規模運用において極めて重要である。