2026-07-05 12:45:30
RDBの「とりあえず削除フラグ」を知らずに実施していた
「とりあえず削除フラグ」がアンチパターンの理由
論理削除がアンチパターンと言われる背景にはクエリが煩雑になったり、UNIQUE制約が使えなくなったり、カーディナリティが低くなるなどがあります。
冷静に考えると似たような役割のカラムを普通に使っていた
少し前に x.com で論理削除が話題になっていました。僕のいる環境では論理削除は使っていないと思っていましたが、冷静に考えると似たような役割のカラムを普通に使っていることに気づきました。
ブログ記事を管理している blog テーブルで例えます。blogs テーブルは削除ではなく記事の公開・非公開を管理する active_flg カラムがあります。僕はこれを「削除じゃないです。公開・非公開を管理するカラムです」と考えていました。しかし、改めて論理削除を考えたときに「これって同じことじゃないか」ということに気づきました。
書籍「失敗から学ぶ RDBの正しい歩き方」(初板第2刷)の5章3項には以下の文章があります。ページでいうとP62です。
テーブルに状態を持たせるのは非常に危険です
このアンチパターンを回避するには、「事実のみを保存する」ことが大切です。
引用元: 失敗から学ぶ RDBの正しい歩き方 https://gihyo.jp/book/2019/978-4-297-10408-5
これは僕の解釈ですが、「とりあえず削除フラグ」がアンチパターンというよりも「ついでに状態を管理するカラムを持つこと」がアンチパターンだと解釈すると血肉になりました。「ついでに」というのがポイントです。何かしらの方法で「状態」を管理する必要があると思うので、「どう扱うか」が大切なのかと思います。
「ついでに状態を管理するカラムを持つこと」を回避する(「とりあえず削除フラグ」を回避する)
書籍の例ではアンチパターンを回避する方法の1つに専用のテーブルを作る内容がありました。
僕のブログ記事の例でこのアンチパターンを回避することを考えると恐らく以下のテーブル設計になると思います。
- blog テーブル{記事ID, 記事タイトル, 記事本文}
- blog_draft テーブル{記事ID}
- blog_public テーブル{記事ID}
- blog_secret テーブル{記事ID}
- blog_delete テーブル{記事ID}
blog_public テーブルにあるものがインターネット公開されるブログ記事になります。
これによって「ついでに状態を管理するカラムを持つこと」は回避できます。その他のテーブルの役割は割愛しますが、それぞれブログ記事の状態を管理する専用のテーブルです。
今更気づいたことにちょっとショック
「削除するなら普通に物理削除でいいじゃん...」と冷笑にも近い感情を抱いていましたが、普通に同じようなことをやっていて反省しました。いや、僕が設計したテーブルの中に「ついでに状態を管理するカラムを持つこと」を実施していたかは忘却の彼方に消えていますが、日頃の違和感はありませんでした。
とは言っても...
僕のいる環境でこのような状態を専用テーブルで管理する能力が「常に」あるかというと「怪しいのでは...?」と思ったりします。
たとえば、ブログ記事を公開から非公開に更新することを考えると、「blog_public テーブルから該当レコードを削除して、blog_secret テーブルにインサートする」という手順を踏むことになると思います。ブラウザ上で「公開から非公開」にするインターフェースを提供する場合は、記事本文などと同じ画面に提供すると思いますが、 RDB 更新の処理では分かれたテーブルを更新することになります。普通に面倒に感じてしまいます。
思いつく限りを考えた結果「よし、『ついでに状態を管理するカラム』を作るか」となるケースはありそうです。というかテーブルの規模にも関係してくると思います。
おわり
おわり