実際にまたは物理的にレコードを削除するのではなく、レコードの論理/ソフト削除(つまり、レコードが削除されたことを示すフラグを設定)を行う利点は何ですか?
これは一般的な方法ですか?
これは安全ですか?
実際にまたは物理的にレコードを削除するのではなく、レコードの論理/ソフト削除(つまり、レコードが削除されたことを示すフラグを設定)を行う利点は何ですか?
これは一般的な方法ですか?
これは安全ですか?
回答:
利点は、履歴を保持し(監査に適しています)、削除する行を参照するデータベース内の他のさまざまなテーブルを介して削除をカスケードすることを心配する必要がないことです。欠点は、フラグを考慮に入れるためにレポート/表示メソッドをコーディングする必要があることです。
それが一般的な慣行である限り、私は「はい」と言いますが、それを使用するかどうかは、ビジネスニーズによって異なります。
編集:別の不利な点の考え-テーブルに一意のインデックスがある場合、削除されたレコードは引き続き「1」レコードを使用するため、その可能性についてもコーディングする必要があります(たとえば、一意のインデックスを持つユーザーテーブル)ユーザー名;削除されたレコードは、新しいレコードの削除されたユーザーのユーザー名を引き続きブロックします。これを回避するには、削除されたユーザー名の列にGUIDを追加できますが、これは私がお勧めしない非常にハックな回避策です。一度ユーザー名を使用すると、それを置き換えることはできないというルールを設定することをお勧めします。)
CREATE UNIQUE INDEX ... WHERE DELETED_AT is null
(PostgreSQLの場合)削除日があるすべての行にはインデックスが作成されません。(代わりに非固有のインデックスに含めることができます。)
論理削除は一般的な方法ですか?はい、私はこれを多くの場所で見ました。安全ですか?それは本当にあなたがそれを削除する前のデータよりも安全性が低いかどうかに依存しますか?
私が技術リーダーだったとき、私はチームにすべてのデータを保持するように要求しましたが、そのときにすべてのデータを使用してさまざまなBIアプリケーションを構築することを知っていました。あります。これは、監査、トラブルシューティング、およびレポートの観点からは問題ありませんでした(これはB2Bトランザクション用のeコマース/ツールサイトであり、誰かがツールを使用した場合、後でアカウントがオフになった場合でも記録することを望みました)。それにはいくつかの欠点がありました。
欠点には次のようなものがあります(すでに述べた他のものは含みません):
論理的、物理的削除、またはアーカイブを使用することを決定するとき、私は自分に次の質問をします。
Activated
テーブルとDeactivated
テーブルスキーマ- Id,Name,etc..
行にActivated
- 1001,Smith007,etc...
彼が非アクティブ化されると、その後、我々はSmithのすべてが、ID列をクリアすることができますActivated
し、彼を追加しますDeactivated
。
少し遅れる可能性がありますが、論理的またはソフト削除に関するPinal Daveのブログ投稿を確認することをお勧めします。
私はこの種のデザイン[ソフト削除]がまったく好きではありません。私は、必要なデータのみを単一のテーブルに入れ、不要なデータをアーカイブされたテーブルに移動するアーキテクチャーを確信しています。isDeleted列をたどる代わりに、2つの異なるテーブルの使用をお勧めします。1つは注文、もう1つは削除された注文です。その場合、両方のテーブルを維持する必要がありますが、実際には、維持するのは非常に簡単です。isDeleted列にUPDATEステートメントを書き込むときは、INSERT INTOを別のテーブルに書き込み、元のテーブルからDELETEします。ロールバックの場合は、別のINSERT INTOとDELETEを逆の順序で書き込みます。トランザクションの失敗が心配な場合は、このコードをTRANSACTIONでラップしてください。
上記の状況で、小さいテーブルと大きいテーブルの利点は何ですか?
- 小さなテーブルはメンテナンスが簡単です
- インデックスの再構築操作ははるかに高速です
- アーカイブデータを別のファイルグループに移動すると、プライマリファイルグループの負荷が軽減されます(すべてのファイルグループが別のシステムにあると見なされます)。これにより、バックアップも高速化されます。
- サイズが小さいため、統計情報は頻繁に更新され、リソースの消費量が少なくなります。
- インデックスのサイズが小さくなります
- テーブルのサイズは小さいほど、テーブルのパフォーマンスが向上します。
私はNoSQL開発者であり、最後の仕事で、常に誰かにとって重要なデータを処理しました。作成されたその日に誤って削除された場合、最後のバックアップでそれを見つけることができませんでした。昨日から!そのような状況では、一時的な削除によって常に救われました。
タイムスタンプを使用してソフト削除を行い、ドキュメントが削除された日付を登録しました。
IsDeleted = 20150310 //yyyyMMdd
毎週日曜日に、プロセスはデータベース上を歩き、IsDeleted
フィールドをチェックしました。現在の日付とタイムスタンプの差がN日より大きい場合、ドキュメントは完全に削除されました。ドキュメントがまだいくつかのバックアップで利用可能であることを考えると、それを行っても安全でした。
編集:このNoSQLの使用例は、データベースで作成された大きなドキュメントに関するものであり、毎日数十または数百のドキュメントですが、数千または数百万ではありません。一般的に、それらはワークフロープロセスのステータス、データ、添付ファイルを含むドキュメントでした。ユーザーが重要な文書を削除する可能性があったのはそのためです。このユーザーは、管理者権限を持つユーザー、またはドキュメントの所有者である可能性があります。
TL; DR私のユースケースはビッグデータではありませんでした。その場合、別のアプローチが必要になります。
私が使用したパターンの1つは、ミラーテーブルを作成してプライマリテーブルにトリガーをアタッチすることです。これにより、すべての削除(および必要に応じて更新)がミラーテーブルに記録されます。
これにより、削除/変更されたレコードを「再構築」でき、プライマリテーブルを完全に削除して「クリーン」に保つことができます。また、「元に戻す」機能を作成でき、日付、時刻も記録できます、およびミラーテーブルでアクションを実行したユーザー(魔女狩りの状況で非常に貴重です)。
他の利点は、意図的にミラーテーブルからレコードを含めるというトラブルに移動しない限り、プライマリからクエリを実行するときに誤って削除されたレコードを含める可能性がないことです(ライブレコードと削除されたレコードを表示したい場合があります)。
もう1つの利点は、実際の外部キー参照がないため、ミラーテーブルを個別にパージできることです。これにより、ソフト削除を使用しているが、他のテーブルへの参照接続があるプライマリテーブルからのパージと比べて、操作が比較的簡単になります。
他にどんな利点がありますか?-プロジェクトに取り組んでいる多数のコーダーがいて、スキルと詳細レベルに注意を払いながらデータベースの読み取りを行っている場合は、削除されたものを含めないことを忘れずに夜を過ごす必要はありません。レコード(笑、削除されたレコードを含めない= True)。これにより、クライアントが使用可能な現金ポジションを過大評価するような結果になります(つまり、取引システムと同様に)、取引システムで作業する場合、初期の「オーバーヘッド」が少し多い場合でも、堅牢なソリューションの価値がすぐにわかります。
例外:
-ガイドとして、ユーザー、カテゴリなどの「参照」データにはソフト削除を使用し、「ファクト」タイプのデータ、つまりトランザクション履歴にはミラーテーブルへのハード削除を使用します。
特にLine of Businessアプリケーションやユーザーアカウントのコンテキストでは、論理削除の大ファンです。私の理由は単純です。多くの場合、ユーザーがシステムを使用できないようにする(アカウントが削除済みとしてマークされる)ことを望まないことがよくありますが、ユーザーを削除すると、すべての作業などが失われます。
別の一般的なシナリオは、ユーザーが削除された後しばらくしてから再作成される可能性があることです。ユーザーがすべてのデータを削除前の状態のままにしておくことは、ユーザーがデータを再作成する必要がなく、はるかに優れたエクスペリエンスです。
通常、ユーザーを削除することは、ユーザーを無期限に「一時停止」することと考えます。彼らが合法的に戻ってくる必要があるときをあなたは決して知りません。
ほとんどの場合、ソフト削除を行います。その理由は次のとおりです。
isdeleted
すべての場所を確認することは問題ではありませんが、userid
とにかく確認する必要があります(データベースに複数のユーザーからのデータが含まれている場合)。これらの2つのチェックを別の関数に配置する(またはビューを使用する)ことにより、コードによるチェックを実施できます。再:「これは安全ですか?」-それはあなたの意味次第です。
つまり、物理的な削除を行うことで、削除されたデータを誰も見つけられないようにすることができます。そうだとすれば、それは事実です。消去する必要のある機密データを物理的に削除する方が安全です。これは、データベースから完全に削除されるためです。(ただし、バックアップやトランザクションログ、転送中の記録されたバージョンなど、問題のデータの他のコピーが存在する可能性があることを認識してください。たとえば、パケットスニファ-データベースから削除しただけでは別の場所に保存されなかったことを保証します。)
論理的な削除を行うことで、データが失われることがなくなるため、データの安全性が高まります。これも事実です。これは監査シナリオに適しています。この方法で設計する傾向があるのは、いったんデータが生成されると、それが実際になくなることはないという基本的な事実を認めるためです(特に、インターネット検索エンジンによってキャッシュされる機能があった場合は特にそうです)。もちろん、実際の監査シナリオでは、削除が論理的であるだけでなく、更新が変更の時間と変更を行ったアクターとともにログに記録されることも必要です。
データが、それを見ることになっていない人の手に渡らないことを意味する場合、それはアプリケーションとそのセキュリティ構造に完全にかかっています。その点で、論理削除はデータベース内の他の何よりも安全ではありません。
多くのエラーが発生するため、論理削除には強く反対します。
まず最初に、各クエリはIsDeletedフィールドを処理する必要があり、複雑なクエリではエラーの可能性が高くなります。
次に、パフォーマンス:3つだけがアクティブな100000レコードのテーブルを想像してください。データベースのテーブルに対してこの数を乗算します。別のパフォーマンスの問題は、古いレコード(削除されたレコード)を持つ新しいレコードとの競合の可能性です。
私が見る唯一の利点は、レコードの歴史ですが、この結果を達成するための他の方法は、あなたが情報を保存することができますロギング表を作成することができ、たとえば、あります。TableName,OldValues,NewValues,Date,User,[..]
どこ*Values
することができvarchar
、これ形で詳細を書きますfieldname : value
。[..]またはとして情報を保存しxml
ます。
これはすべてのコードまたはトリガを介して達成することができるが、あなただけのあるONEすべてのあなたの歴史を持つテーブル。別のオプションは、指定されたデータベースエンジンが変更を追跡するためのネイティブサポートであるかどうかを確認することです。たとえば、SQL ServerデータベースにはSQL Trackデータ変更があります。
以前は、古いレコードを保持するためだけにソフト削除を行っていました。ユーザーが古いレコードを思ったほど頻繁に表示する必要がないことに気付きました。ユーザーが古いレコードを表示したい場合は、アーカイブまたは監査テーブルから表示できますよね?では、ソフト削除の利点は何ですか?より複雑なクエリステートメントなどにつながるだけです。
以下は、ソフト削除しないことを決定する前に実装したものです。
監査を実装して、すべてのアクティビティ(追加、編集、削除)を記録します。監査にリンクされている外部キーがないことを確認し、このテーブルが保護されており、管理者以外は誰も削除できないことを確認してください。
「トランザクションテーブル」と見なされるテーブルを特定します。これは、長期間保持される可能性が高く、ユーザーが過去のレコードまたはレポートを表示する可能性が非常に高い可能性があります。例えば; 購入取引。このテーブルは、マスターテーブルのID(dept-idなど)を保持するだけでなく、参照としての名前(dept-nameなど)やレポートに必要なその他のフィールドなどの追加情報も保持する必要があります。
マスターテーブルの「アクティブ/非アクティブ」または「有効/無効」または「非表示/表示」レコードを実装します。したがって、ユーザーはレコードを削除する代わりに、マスターレコードを無効化/非アクティブ化できます。この方法の方がはるかに安全です。
ちょうど私の2セントの意見。
カスケード機能などを役に立たないものにするため、データベースはデータベースを実行しません。
挿入などの単純なものの場合、再挿入の場合、その背後のコードは2倍になります。
単に挿入するだけではなく、存在を確認して、存在しない場合は挿入するか、存在する場合は削除フラグを更新すると同時に、他のすべての列を新しい値に更新する必要があります。これは、データベーストランザクションログの更新と見なされ、不正確な監査ログの原因となる新しい挿入ではありません。
テーブルが冗長データで詰まっているため、パフォーマンスの問題が発生します。それは、特に一意性を備えた索引付けで大混乱を演じます。
私は論理削除の大ファンではありません。
Tohidのコメントに返信するために、レコードの履歴を保持したいという同じ問題に直面しましたis_deleted
。また、列が必要かどうかもわかりませんでした。
私たちのpython実装と私たちがヒットした同様のユースケースについて話している。
https://github.com/kvesteri/sqlalchemy-continuumに遭遇しました。これは、対応するテーブルのバージョン管理テーブルを取得する簡単な方法です。コードの最小行と追加、削除、更新の履歴をキャプチャします。
これは単にis_deleted
列を提供するだけではありません。バージョンテーブルをいつでも後方参照して、このエントリで何が起こったかを確認できます。エントリが削除、更新、または追加されたかどうか。
この方法では、is_deleted
列をまったく持つ必要がなく、削除機能は非常に簡単でした。このようis_deleted=False
に、API をマークすることを覚えておく必要もありません。
ソフト削除はプログラミングの慣例であり、データの関連性が高いときにほとんどのアプリケーションで実行されます。エンドユーザーの間違いによる削除が致命的となる可能性がある金融アプリケーションの場合を考えてみます。これは、ソフト削除が適切になる場合です。ソフト削除では、ユーザーは実際にレコードからデータを削除するのではなく、IsDeletedとしてフラグが付けられます(通常の規則による)。
EF 6.xまたはEF 7以降では、Softdeleteが属性として追加されていますが、今のところカスタム属性を作成する必要があります。
SoftDeleteをデータベース設計で使用することを強くお勧めします。これは、プログラミングの慣習としては良い慣例です。
一部のデータを公開したくないが、歴史的な理由でそれを保持する必要があるため、ほとんどの場合ソフト削除が使用されます(製品は製造中止になる可能性があるため、新しいトランザクションは必要ありませんが、それでも作業する必要があります販売取引の履歴)。ちなみに、これを処理するために製品を参照する代わりに、販売取引データの製品情報値をコピーしている人もいます。
実際には、表示/非表示またはアクティブ/非アクティブな機能の言い換えのように見えます。それがビジネスの世界では「削除」の意味だからです。ターミネーターは人を削除するかもしれませんが、ボスは彼らを解雇するだけだと言いたいです。
このプラクティスはかなり一般的なパターンであり、さまざまな理由で多くのアプリケーションで使用されています。これを達成する唯一の方法ではないので、何千人もの人々がそれが素晴らしいまたはでたらめであると言って、両方にかなり良い議論があるでしょう。
セキュリティの観点から見ると、SoftDeleteはAuditのジョブを置き換えず、バックアップのジョブも置き換えません。「2つのバックアップケース間の挿入/削除」を恐れている場合は、完全復旧モデルまたは一括復旧モデルについてお読みください。SoftDeleteは回復プロセスをより簡単にすることができることを認めます。
あなたの要件を知るのはあなた次第です。
別の方法として、Mobile Linkを介して更新するリモートデバイスを使用するユーザーがいます。サーバーデータベースのレコードを削除しても、それらのレコードがクライアントデータベースで削除済みとしてマークされることはありません。
したがって、両方を行います。クライアントと協力して、データを回復できる期間を決定します。たとえば、一般に顧客と製品は、クライアントが削除する必要があると言うまでアクティブですが、販売の履歴は13か月間のみ保持され、その後自動的に削除されます。クライアントは、削除された顧客と製品を2か月間保持し、履歴を6か月間保持したい場合があります。
したがって、これらのパラメーターに従って論理的に削除されたものをマークするスクリプトを夜間に実行し、2か月または6か月後に、論理的に削除されたマークが付けられたものはすべて完全に削除されます。
私たちは、スマートフォンなどのメモリが限られているクライアントデバイスに巨大なデータベースを配置することよりも、データのセキュリティを重視しています。4年間、週に2回200製品を注文するクライアントは、81,000行以上の履歴を持ち、そのうち75%は見たとしても気にしません。
それはすべて、システムとそのデータの使用例に依存します。
たとえば、政府規制システム(たとえば、品質システムの一部と見なされ、電子記録に関するFDAガイドラインに従う必要がある製薬会社のシステム)について話している場合は、完全削除を行わないほうがよいでしょう。FDAの監査人が来て、製品番号ABC-123に関連するシステム内のすべてのレコードを要求することができ、すべてのデータがより適切に利用可能になります。ビジネスプロセスの所有者が、今後の新しいレコードで製品番号ABC-123を使用することをシステムに許可してはならない、と言っている場合は、履歴データを保持しながら、システム内で「非アクティブ」にするために代わりにソフト削除メソッドを使用します。
ただし、システムとそのデータに「北極での天気の追跡」などの使用例がある場合もあります。たぶん、1時間に1回温度測定値を取得し、1日の終わりに1日の平均を集計します。1時間ごとのデータは、集計後に使用されなくなる可能性があり、集計を作成した後、1時間ごとの読み取り値を完全に削除します。(これはでっち上げの簡単な例です。)
重要なのは、それはすべてシステムとそのデータのユースケースに依存するものであり、純粋に技術的な観点から行われる決定ではないということです。
上手!皆が言ったように、それは状況に依存します。
UserNameやEmailIDなどの列にインデックスがあり、同じUserNameやEmailIDが再び使用されることを期待していない場合。ソフト削除を使用できます。
ただし、SELECT操作で主キーが使用されているかどうかを常に確認してください。SELECTステートメントが主キーを使用している場合、WHERE句でフラグを追加しても大きな違いはありません。例を見てみましょう(疑似):
テーブルユーザー(UserID [主キー]、EmailID、IsDeleted)
SELECT * FROM Users where UserID = 123456 and IsDeleted = 0
UserID列には主キーがあるため、このクエリはパフォーマンスの点で違いはありません。最初は、PKに基づいてテーブルをスキャンし、次の条件を実行します。
一時的削除がまったく機能しない場合:
主にすべてのWebサイトでのサインアップは、EmailIDを一意の識別として使用します。EmailIDがFacebook、G +などのWebサイトで使用されると、それを他のユーザーが使用することはできません。
ユーザーがWebサイトから自分のプロファイルを削除したい日が来ます。これで、論理削除を行うと、そのユーザーは二度と登録できなくなります。また、同じEmailIDを使用して再度登録しても、履歴全体が復元されるわけではありません。誰もが知っている、削除は削除を意味します。このようなシナリオでは、物理的に削除する必要があります。ただし、アカウントの履歴全体を維持するには、そのようなレコードを常にアーカイブテーブルまたは削除されたテーブルのいずれかにアーカイブする必要があります。
はい、多くの外部テーブルがある状況では、処理はかなり面倒です。
また、ソフト/論理削除を行うとテーブルサイズが大きくなるため、インデックスサイズも大きくなることに注意してください。
私はすでに別の投稿で答えました。ただし、ここでの質問には私の回答のほうが適していると思います。
:ソフト削除のための私の現実的な解決策には、次の列を持つ新しいテーブルを作成することによってアーカイブされた
original_id
、table_name
、payload
、(およびオプションの主キー`ID)。どこに
original_id
削除されたレコードのオリジナルのidは、さtable_name
(削除されたレコードのテーブル名で"user"
、あなたの場合)、payload
削除されたレコードのすべての列からJSON-文字列化文字列です。また
original_id
、後のデータ取得のために列にインデックスを作成することをお勧めします。この方法でデータをアーカイブします。これらの利点があります
- 履歴内のすべてのデータを追跡します
- 削除されたレコードのテーブル構造に関係なく、テーブルからレコードをアーカイブする場所は1つだけ
- 元のテーブルの一意のインデックスの心配はありません
- 元のテーブルの外部インデックスをチェックする心配はありません
WHERE
削除を確認するために、すべてのクエリに句がありませんこれはすでに、ソフト削除が実際に良いアイデアではない理由を説明する議論 です。論理削除では、レコードのカウントなど、将来的にいくつかの潜在的な問題が発生します...
Adventagesは、データの保存/永続化です。問題は、大量のソフト削除を含むテーブルからデータをクエリまたは取得するときのパフォーマンスの低下です。我々の場合には、我々は両方の組み合わせを使用します。他の人が、前の回答で述べてきたように、我々soft-delete
users/clients/customers
例えば、とhard-delete
のitems/products/merchandise
蜂keeptする必要はありません重複したレコードがあるテーブル。