iTAC_Technical_Documents

アイタックソリューションズ株式会社

ブログ名

物理削除 と 論理削除 について

【DB設計】物理削除 と 論理削除 どっちがいいの?

DBを設計する際、レコードの削除方法には主に物理削除論理削除の2通りがあります。
削除方法は選択できますが、先に結論を言ってしまうと業務システムでは基本的に論理削除が推奨されます
その理由を各削除方法のメリットとデメリットやデータの種類、実際の例を示して説明していきたいと思います。

物理削除とは


SQLでDELETE文を発行してレコードを削除することを指します。
原則として容易にデータの復活はできません(バックアップから復元することはできます)。

メリット

  • 削除=DELETE文発行であるため、実装しやすい。
  • レコードが削除される為、ストレージを圧迫しにくくなる。

デメリット

  • 容易に復元したり削除されたデータを参照することができない。

論理削除とは


テーブルに削除フラグ(Boolean型)を項目として用意し、そのTRUE/FALSEで削除をされたかどうか管理する方法のことを指します。
基本的には、削除フラグにはデフォルトでFALSEを持たせておき、削除されたらそのレコードの削除フラグをTRUEにします。
つまり、通常データ抽出する際は必ず削除フラグがFALSEのものだけを対象とします。

メリット

  • ユーザが間違えて削除した場合に元に(バックアップからなどの手間をかけずに)戻せる。
  • システムのバグで削除されてしまった場合も復元が容易になる。

デメリット

  • 消してもデータが減らないのでストレージを圧迫する可能性がある。
  • 削除のアクションがUPDATEになるため直観的に理解しづらい。
  • 論理削除されてる事を前提にアプリを作るとデータが複雑に絡み合うので、実装難易度が上がる。

データの種類


データにはマスタデータとトランザクションデータがあります。
簡単に説明すると以下です。

マスタデータ:蓄積されず、変更があったら値が更新されていくデータ。(例:アカウント情報データ)

トランザクションデータ:基本的に値は更新されず、蓄積されていくデータ。(例:ECサイトのアカウントの注文履歴データ)

DB設計する際はマスタデータとトランザクションデータはテーブルを分け、外部キーで紐づけます。

トランザクションデータは論理削除


業務システムではトランザクションデータは論理削除が選択されます。理由は、トランザクションデータはログや履歴のデータであり、蓄積されることが前提のデータだからです。
上の例でいうと、アカウントの注文履歴データを物理削除してしまったらそのデータを追うことができなくなり、のちに不都合が生じる場合があります。削除を前提とせず、ログとして残すのがトランザクションデータです。

マスタデータも論理削除が良い場合が多い


一方で、マスタデータはどうでしょうか。変更があれば値を更新し、変更前の値を蓄積することはありません。特にマスタデータはアカウント情報など重要なデータが詰まっています。データが必要なくなれば、物理削除してしまったほうが良いように感じるかもしれません。
しかし、マスタデータも論理削除が選択されることが多いです。理由は、マスタデータを物理削除してしまうと、マスタデータに紐づいたトランザクションデータがある場合、参照元を追えなくなってしまうためです。

例えば上の例で出した、アカウント情報データ(マスタデータ)とアカウントの注文履歴データ(トランザクションデータ)では、アカウントの注文履歴データは残っているのに注文したアカウントの情報が残っていないという齟齬が生じてしまいます。これでは、注文履歴データから誰が注文したかを追いたい時に意味がありません。

上記から、基本的にはマスタデータも論理削除とすることが多いです。逆に、もし扱っているマスタデータにトランザクションデータが紐づいていない場合や、トランザクションデータからマスタデータを参照することを想定しない場合はマスタデータは物理削除でもいいかもしれません。

実際に論理削除を実装する場合の注意点


論理削除を実装する際は、削除フラグのカラムに加えて、いつ削除されたかのカラム、誰が削除したかのカラムも作成しておくと良いです。
以下は論理削除を実装する際のテーブルの例です。

スクリーンショット (34).png

上の画像は、健康診断管理アプリの画像データテーブルです。
論理削除を実装するために以下のカラムを追加しました。

delete_flag:Boolean型。falseなら未削除、trueなら削除されたとして判定する。
flag_update_at:Timestamp型。削除された日時を格納する。
flag_update_by:誰によって削除されたかを格納する。

論理削除を復元させる機能は必要?


これに関しては、復元させる頻度によります。
例えば、顧客数や受注数が膨大なECサイトは、1000顧客あたり年に一度くらいの頻度であっても36万顧客がいれば一日一度は発生する計算になります。こうなるともはや通常オペレーション扱いで復元を機能化します。月に一度程度でも操作に手間がかかるなら、機能化する場合があります。
そうでないなら、アドミン権限の者がSQLで直接修正で構いません。

まとめ


以上より、基本的に論理削除を選択することが多いです。
ただ、DB設計を考える際は全部が全部を論理削除するとして考えるというよりは、様々な場面を想定して考えていく必要があり、結果的に論理削除を採用しておいたほうが齟齬が生じない場面が多いということだと思います。

新しく開発する際は、論理削除を選択することを視野にDB設計を考えていきましょう!


戻る