ブログ記事
「削除フラグ」が将来の不具合を予約する理由──『失敗から学ぶRDBの正しい歩き方』のアンチパターン20選
アプリケーションのコードは書き直せる。フレームワークを変えることもできる。しかしデータベースに一度入ったデータは、システムの中で最も長く残り続ける。設計の誤りがその後の開発コスト全体に積み重なっていく。
曽根壮大著『失敗から学ぶRDBの正しい歩き方』(技術評論社、2019年)は、現場でよく見かける RDB 設計・運用のアンチパターン 20 種を、なぜ問題なのか・どう解決するかという構造で整理する。
1. 「削除フラグ」はクエリを際限なく複雑にする
退会したユーザーや削除した注文を残すために「削除フラグ」カラムを追加するのは、一見シンプルな解決策に見える。しかし本書はこの設計を、将来に向けた問題の予約として位置づける。
すべての SELECT クエリに WHERE deleted_flag = 0 が付くことで、インデックスの選択度(カーディナリティ)が極端に下がる。削除されたレコードが増えるにつれてパフォーマンスが劣化する。UNIQUE 制約による重複防止も、削除フラグを考慮しなければ正しく機能しない。
本書が提案するのは「事実のみを保存する」設計だ。現在有効なデータと削除済みデータをテーブルレベルで分離する、あるいは VIEW を使って有効データのみをアプリケーション側に見せる。状態をテーブル構造で持たせない設計が、長期的なクエリの複雑化を防ぐ。
flowchart TD
subgraph NG["❌ 削除フラグ設計"]
T1["users テーブル\nid | name | deleted_flag\n全クエリに WHERE deleted_flag=0 が必要\nUNIQUE 制約が正しく機能しない"]
end
subgraph OK["✅ テーブル分離設計"]
T2A["users テーブル\n(有効データのみ)"]
T2B["deleted_users テーブル\n(削除済みを別管理)"]
end
style NG fill:#fce8e8,stroke:#e53935
style OK fill:#e8f8e8,stroke:#4caf50
2. 上書き UPDATE が「ビジネスの歴史」を消す
消費税率の変更や商品価格の改定を、マスタテーブルの UPDATE で対応するのは一般的だ。しかし過去の時点で「いくらで取引されたか」という事実は、上書きの瞬間に失われる。返品処理や監査対応が必要になったときに、過去の状態を復元する手段がなくなる。
本書はこのパターンに対して、変更を UPDATE で上書きするのではなく、新しい事実を INSERT として追記する履歴設計を論じる。ただし追記し続けることはデータ量の増加を伴い、インデックス検索の劣化につながるトレードオフも存在する。データの用途によって、専用の履歴テーブルを設ける、分析基盤にログを転送するなど複数の選択肢が示される。
3. インデックスは「追加するより削除の方が難しい」
クエリが遅いたびに複合インデックスを追加する「インデックスショットガン」は、ディスク容量の圧迫とデータ更新処理の遅延を引き起こす。
本書は SQL の実行エンジンが FROM → WHERE → ORDER BY という順序でデータを処理する流れを説明した上で、インデックスが効果を発揮する条件を整理する。対象テーブルの 10% 未満のデータを絞り込む SELECT でなければ、インデックスが使われないケースがあるという基準も示す。
インデックスの管理については「MENTOR の原則」(Measure・Explain・Nominate・Test・Optimize・Rebuild)を使った継続的な運用サイクルが提案される。一度追加したインデックスは削除の判断が難しいため、追加前に測定と実行計画の確認を行う習慣が重要だという立場だ。
4. SQL が複雑怪奇になってきたら
「機能を追加するたびに WHERE 句へ削除フラグや状態フラグの条件が増え、どのクエリを直すと何が壊れるのか読めなくなってきた」——本書が最も効くのはこの段階のエンジニアだ。ORM が生成するとおりにテーブルを作り、データ量が増えた本番でスロークエリや過去価格の集計ズレに直面してから、設計の初期判断がボトルネックだったと気づく。本書は 20 の失敗例をトラブルの実例から逆算して並べているため、いま自分が踏んでいる地雷を名前付きで特定し、代替設計へ引き上げる手がかりになる。「なんとなく動いている」設計を、理由を言葉にできる設計へ変えたい人に効く一冊だ。
5. 2 冊目の実務書として読む本
難易度は中級。インデックス・トランザクション・正規化といった用語は「一定レベルで理解している」前提で進むため、読む時期を選ぶ本だ。
向いている人
- 削除フラグや状態フラグで WHERE 句が膨らみ、修正の影響範囲が追えなくなっている Web バックエンド開発者
- デッドロックやロック競合に、再起動やプロセスキルで対症療法を重ねている運用・SRE 担当者
向いていない人
- RDB をこれから触る人。基礎の定義を飛ばして進むため、1 冊目としては挫折しやすい。
SQL実践入門などで SQL とテーブル設計の地力を付けてからのほうが順序として合う - SQL チューニングやデータモデリングの標準理論を習得済みのシニア層。扱うアンチパターンの多くが「当然避けるべき事柄」の範囲に収まり、既知が多く感じられる
6. 『SQLアンチパターン』との棲み分け
同じ「アンチパターン」を冠する Karwin の SQLアンチパターン 第2版 と紛らわしいが、守備範囲が違う。Karwin 本が論理設計と SQL レベルの失敗、つまり設計時の誤りを扱うのに対し、本書はバックアップ未検証・監視の欠如・ロック競合・コンフィグ放置など、本番運用で初めて牙をむく落とし穴を扱う。設計時の失敗を Karwin 本で、運用時の失敗を本書で押さえると、設計から運用までの失敗が見渡せる。どちらが上位ということはなく、対象とする時間軸の違う 2 冊として並べて使える。
7. マネージド DB 時代に、どこまで効くか
2019 年刊の本書が説く運用の教え——バックアップのリストア検証、スロークエリ監視、コンフィグのチューニング——は、Amazon RDS のようなフルマネージドサービスでは標準機能が肩代わりする部分がある。運用系の警鐘は、環境によっては読み替えが要る。一方で、削除フラグ・履歴の上書き・JSON の乱用・状態の埋め込みといった論理設計の失敗は、マネージドかどうかに関係なく設計者の手に残り続ける。ここが本書の古びない核だ。逆に、読み取りレプリカの遅延による一時的な不整合のような、クラウドで新しく生まれた落とし穴までは踏み込んでいない。運用の章はいまのインフラに合わせて補いつつ、論理設計の章を軸に読むのが現実的な使い方になる。
8. 読み終えた後に向かう先
単一のリレーショナルデータベースの設計と運用が腹落ちしたら、次は複数のデータストアが絡む大規模システムへ視野を広げたい。DevBookPath が本書の次に挙げるのは データ指向アプリケーションデザイン だ。本書が 1 つの RDB の中で完結させていた整合性やパフォーマンスの話を、複製・分割・障害といったデータシステム全体の原理へと押し広げてくれる。読み終えたその日にできる一歩としては、手元のスキーマから削除フラグを 1 つ選び、有効データと削除済みをテーブルで分けられないか検討してみるとよい。あるいは、気になるスロークエリを 1 本 EXPLAIN にかけて実行計画を眺めれば、MENTOR の測定サイクルはそこから始まる。
筆者の体験から
管理画面のDB改修を任された頃、既存テーブルには用途の読めないカラムが並び、機能を1つ追加するだけでWHERE句を何本も直す羽目になっていた。先輩に聞いても「昔からこうなってる」としか返ってこず、本書のタイトルに自分が踏んでいる地雷の名前を見た気がして手に取った。
読み終えてからは、カラム追加の提案が来たときに「1つのカラムに複数の意味を混ぜていないか」を確認するようになった。担当していたstatusカラムも1が下書き・2が公開・3が非公開の後に4(削除予定)が足され、新ステータス追加時にWHERE句の考慮漏れが起き、削除予定のデータが一覧に表示される不具合を出してしまった。原因を追う中で第7章「隠された状態」を読み、腹落ちしてカラムの棚卸しを提案するきっかけになった。
ただし追記型の履歴設計を全テーブルに広げるのは現実的でなく、優先度をつけて一部にとどめた。バックアップ検証や監視の話も、マネージドDBの環境では肩代わりされる部分が多く、鵜呑みにはできなかった。
DevBookPath のマップで確認する
この本の学習パス上の位置づけ・前後の読書順は、DevBookPath のグラフで辿れます。
👉 バックエンドの地図を見る / 👉 データベースの地図を見る
本記事のリンクには Amazon アソシエイト等の広告が含まれる場合があります。リンク経由の購入で運営者に紹介料が支払われることがあります。
この記事を共有
この地図を共有