24
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[fukabori fm ep27より] 論理削除とその解法メモ

Posted at

削除フラグ(論理削除)について

fukabori fm ep27 から文字起こしとちょっと要約
API開発や設計に携わる人は必聴だと思う素晴らしい回だったのでとったメモを公開しておきます。権利とかで消したほうがよければ削除します。一回しか聞いてないのでよく理解したい人はリンクから聞いてください。。

論理削除の定義

rdb において、データの削除時に実際の削除ではなく、カラムにdeleted_atなどフラグを持たせて削除したことにする仕様
sqlのdelete 文を使わない。update 文を使う

反対とされる物理削除とは

delete 文を使ってデータを削除する

論理削除はなぜ生まれたか

delete 文を使ってデータが見れなくなるという恐怖
削除したデータを検索したい
データをログとして残しておきたい(サービスの保全期間など)
ユーザの誤った操作で削除したとき、元に戻したい

論理削除はアンチパターン?

アンチパターン。よかれと思ってやったことが悪い結果になってしまうこと。
sql アンチパターンより
とりあえず削除フラグ。-> テーブル全てに削除フラグをつける。

なぜかというと、where句に必ずdeleted_atが入る。
join した場合も必ずdeleted_at が必要。可読性も悪い。
削除フラグも含めたユニーク制約も必要になってくる。できてないとセレクトしたときに2件引っかかるパターンがでてくる。
そうなると、limit 1 が必要になってくる。

テーブルにフラグが増えていく

状態を判断するためのカラムがどんどん増えるとき

解法

論理削除。世の中にはない概念、
システム屋特有の言葉。顧客には関係ない。顧客から要望が出ることもない。
顧客の本当の要求を深掘りするべき。システム屋に都合のいい概念に持ち込まない

社員の退職を論理削除ではなく、退職という状態として議論する。
復職した場合どうするかとか。紐づくデータをどうしたいとか。

システムにはどうも可視性制御が必要な場面がある。状態遷移など。
例えば記事の公開非公開。削除。タイマー投稿。下書き。
これらを考えることなしにとりあえず削除フラグは思考停止につながる。
アンチパターンにならないために要求・概念を捉えて設計をしましょう

大体のORMには論理削除の実装があるから楽に実装できてしまう。
過去はis_deleted: bool だった
それは情報量少ないということで、deleted_at: datetime が利用されることになった。

対象の状態遷移を考え、設計に反映させる
SoftDelete
HardDelete

Doctrine php のormapper
v1 から v2 でsoftDeleteサポートやめた
state pattern を使いなさい
status カラムをいれて、enum なり varchar で値をいれる。

state pattern が使えないケースって?
特にないと思われる

論理削除のプラグイン探すんじゃなくてstate machine のプラグインさがそう
不正な状態遷移を防げる
状態遷移の向きを捉えておく。向きを定義する。遷移が飛ばないように。
status が一気にpublish にならないとか。draft -> 審査 -> publish のstateで
draft -> publish にならないように

rails で aasm というstate machine plugin がある
transition とか定義できる。

履歴テーブルに移す

ユーザからは見せたくないけど、データとして残したいテーブル

users テーブルにトリガつくってdelete したら deleted_users に入れるようにする
archive_** テーブル

どちらをとるかだけど、削除のデータが多くなるテーブルでは、こちらが向いている
検索パフォーマンスが落ちてしまう。インデックスが無駄に消費される。
データの比率の見通しも重要

更新も削除も何もしない

退職って削除じゃないよね。情報の追加だよね。
操作の事実を消さずに残していく
特にエンタープライズで重要
更新も削除もデータの改ざん、データを全て残すのが正しいのでは。
なので、insert と select しかしない
何が起こるかというと、改ざんがない。最新のdate time のレコード引っ張ってくれば
必ずそれが正だとわかる
イベントソーシングの考えかな
データが増えるなら金を積む

現役のデータは必ず最新のデータ、order by しないといけなくなる
web 側でやると辛い。ユーザ数がエンプラと比べるとはるかに多いので。

T字型のテーブル設計

イミュータブルデータモデル

update_at のカラムがおかしい
更新を許すものと許さないものをしっかり判断しましょう。

解決できていない問題

誤った操作をすぐに元に戻したい
-> 間違えにくいUIを作りましょう。guide の削除は guide 名いれさせるとか確認画面とか

10分遅れのセカンダリデータベース用意するとか。遅延レプリケーションでサルベージできる。
誤操作の物理削除に対する一つの解。(ただし、t_wadaさんが調べて出てきたやつで、実際に運用したことはない)

まとめ

論理削除は現実世界にない解法のため、それがありふれているのは思考停止になっているので注意
現実世界の言葉(顧客)に耳を傾け、設計に落とし込む。状態を捉える、定義する。

自分も論理削除には懐疑的で、他のテーブルに移したりしたほうがいいのかなと思ってたが実際にはやったことがなかった。ただ、上で挙げられていたデメリットの他に、ORMマッパー以外でクエリするときにdeleted_at をつけ忘れてこの結果正しいんだっけと混乱することが多々あったりした。status で管理されていれば、頭の中でこの情報をとりたいという風に自然とクエリが思いつくのでstateパターンによせてくのがいいのかなと。顧客の声や、実現したい機能の要求をしっかり掘り下げていくことでフラグで埋め尽くされるテーブルがなくなり、データモデルがわかりやすくなるので議論を行なっていくのが結局大事だなと思った。

24
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?