論理削除をやめて状態をテーブルで分けるDB設計
DRANK
はじめに業務システムを作っていると、退会したユーザーや削除した記事を「消えたことにしたいけれど履歴は残したい」という要件によく出会うかと思います。このときによく見るのが論理削除と呼ばれる手法で、deleted_at のような列を足して WHERE deleted_at IS NULL で取り出すというものです。導入は手軽な反面、実際に運用していくとじわじわと辛さが出てくる手法でもあるかなと思っています。クエリの度に WHERE deleted_at IS NULL を書く必要があり、一箇所でも書き忘れると削除済みのレコードが返ってきてしまいます。ORM のデフォルトスコープで隠すという手もありますが、今度は削除済みを含めたい場面で抜け道を作ることになります。さらに、同じメールアドレスが削除済みと未削除で 2 件並べてしまえるためユニーク制約が機能しなくなる、外部キーの参照先が生きているかを DB では保証できなくなる、削除済みレコードが本番テーブルに溜まり続けてインデックスや実行計画に影響してくる、といった問題も次第に効いてきます。元を辿ると、ライフサイクルの異なる状態を 1 つのテーブルに同居させているところが原因ではないかなと思います。在籍中のユーザーと…