盲目的に削除フラグを導入してはいけない
1. 状況
全てのテーブルに削除フラグが追加されている
- 全てのテーブルに削除フラグカラムが追加されている(
delete_flag/is_deleted/deleted_atなど)
- データの削除は全て削除フラグによる論理削除によって行う方針になっており、DELETE文による削除(物理削除)は禁止になっている
deleted_atなどで「いつ削除されたか」という情報を管理していることになっている
2. 問題
クエリの複雑化とバグの温床
- すべての
SELECT 文に WHERE delete_flag = 0 を付与する必要があり、一件でも忘れると削除済みデータが画面に表示されるバグに直結する
Unique制約の形骸化
- 削除済みデータそのものはテーブルに残り続ける為、ユニーク制約が機能しない/ユニーク制約を外す運用を選択せざるを得ない
- 例えば、退会したユーザーが再度登録したい場合、同じメールアドレスで再登録できないなど
パフォーマンスの劣化
- 削除済みデータがテーブル内に残り続ける為、インデックスのサイズが肥大化と検索効率低下を招く
- 更に削除フラグは真偽値なのでカーディナリティが低く、インデックスが有効に機能しない
リレーションシップの崩壊
- 親レコードを論理削除しても子レコードが残ってしまうため、アプリケーション側で複雑な整合性チェックを実装する必要が生じる
- 当然、複雑なロジックは不具合の温床になり、保守性と生産性を低下させる
監査要件の未達成
deleted_atカラムによって、deleted_atがNullなら有効データ、日付が入っていれば無効データとする設計スタイルがある
- このような設計では
deleted_atによって「いつ削除されたか」という情報を管理していると主張されることが多い
- しかし、論理削除 → 復活 → 再度論理削除と複数回のデータの削除と復活が行われると最早「いつ削除されたか」「何度削除されたか」という情報は失われてしまう
- データの復活が容易という理由で論理削除を選択しているのに、その操作履歴は失われるという本末転倒な事態になっている
- つまり、データ変更の監査要求を満たせないので要件を実現することができない欠陥仕様ということになる
3. 原因
思考停止
- 安易に「データが消えるのは怖い」「後で使うかもしれない」と考え、データの復活が容易な論理削除を選択している
- テーブル設計の標準化として「全テーブル共通カラム」を設ける際、深く考えずに削除フラグを含めてしまっている
- など、設計者の思考停止やスキル不足
ビジネスロジックへの考慮不足/検討不足
- 「なぜそのデータが不要になったのか」という業務上の意味(キャンセル、退会、期間終了など)を深く考察できていない
- 一律に「削除」という言葉で片付けてしまっているので「削除フラグ」以外の選択肢が生まれない
- DB設計において必要な思考能力/検討能力が不足している
怠惰
- バックアップや監査ログによる復旧手段を検討せず、DB上のテーブルに対するフラグ操作のみでデータ復元を完結させようとしている
4. 対策
ビジネス状態(Status)への昇格
- 単なる
0/1 のフラグではなく、status カラムとして「キャンセル」「退会」「アーカイブ」など、業務に即した状態遷移を表現する
履歴テーブルへの移動
- メインテーブルからは物理削除し、削除したデータは「監査ログ(Audit Log)」や「履歴テーブル」などに移動させることで、本番環境の検索効率とトレーサビリティを両立させる
有効期間(Validity Period)による管理
- マスタデータなどで適用期間が重要な場合は、フラグではなく
start_date と end_date による期間管理を導入し、事実としての記録を保持する事を検討する
- 例えば、消費税の税率や年度ごとの算出比率など
ビュー(View)の活用
- どうしても論理削除が必要な場合は、有効なデータのみを表示するビューを定義し、アプリケーションからはそのビューを参照するようにしてクエリのミスを防ぐ
5. 注意事項
論理削除が必要となる場面もある
- 論理削除は基本的に避けるべきアンチパターンだが、論理削除を選択する事が合理的である場面も存在する
- 論理削除が合理的な場面:
- 法的要件で削除履歴の保持が必須である場合(ただし、削除フラグより監査ログテーブルへの書き込みの方がより優れている)
- ユーザーが自身で削除・復元を頻繁に行うアプリケーション(ゴミ箱機能など)
- 関連データが多すぎて物理削除のコストが高い場合(大量のカスケード削除が走ってしまうなど)
物理削除すればよいという問題でもない
- 削除フラグによる論理削除はよくない → では物理削除を使おうという発想もよろしくない
- 先述したように「データが不要になる」は「削除」を意味するわけではなく、ビジネスルール上の状態が変わっただけである事が大半である
- 物理削除も「削除されている/削除されていない」の2値しか表現できないので、表現力は論理削除と変わらない
- 適切な「状態」を定義することが重要である
参考資料