コンピューター機器やその他のハードウェアデバイスを追跡する在庫データベースを構築しています。デバイスの寿命のある時点で、デバイスは廃棄され、アーカイブされます。アーカイブされた後は、サービスから削除され、適切に廃棄されるため、追跡する必要があります。私は元々、アクティブデータベースからの削除のトリガーを使用してデータを受信するアクティブデータベースの正確なレプリカを使用してアーカイブメカニズムを設計しました。アーカイブデータベースには、関連するすべてのテーブルのレプリカが含まれています。これは、特定の外部関連レコードが適切ではなくなったため、新しいデバイスで使用するためにユーザーがアクセスできないようにする必要がありますが、参照整合性とアーカイブテーブルでのクエリに必要です。ここでのアーカイブの概念は、単に履歴やログを保持するだけではないことに注意してください。アーカイブはビジネスプロセスの一部であり、ユーザーはアクティブでアーカイブされているデバイスのクエリと更新を行う必要があります。
以下のERDでは、Inventory.DeviceType
テーブルを例として使用し、すべてのエントリと更新がArchive.DeviceType
テーブルにコピーされます。ユーザーが特定のデバイスタイプのインベントリレコードを入力できなくなった場合、そのレコードはInventory.DeviceType
テーブルから削除されますが、アーカイブテーブルには残ります。このパターンはすべてのテーブルで使用され、アーカイブが有効なデータ、つまりすべてのテーブルのレプリカを参照するようにします。
アクティブテーブルの例(その他の関連テーブルは省略)
アーカイブテーブルの例(その他の関連テーブルは省略)
問題
デバイスがアクティブであるかアーカイブされているかわからない場合に、データベースにクエリを実行する方法を理解しようとしていますか?たとえば、ユーザーがシリアル番号を持っていて、デバイスに関する情報を知りたい場合、それらがアーカイブされているかどうかを知りません。
オプション1:ユニオンallに基づいてビューを作成しますか?
オプション2:アクティブなデータベースをクエリし、最初のクエリが何も返さない場合はアーカイブをクエリしますか?
物語は続く...
あるアソシエートは、アーカイブデータベースを削除し、ソフト削除スキームを使用することを提案しました。私はこのアイデアを使用してモデルを構築し、その後、他の多くの問題に直面し始めました。
ソフト削除スキームを使用した同じテーブルを次に示します。
ソフト削除の例
この設定では、IsArchived
フィールドをtrueに設定し、ArchivedDate
を入力することにより、デバイスがアーカイブされます。デバイスがアクティブかアーカイブ済みかに関係なく、どのデバイスにも簡単にクエリできます。 (IsActive
フィールドは無関係な概念に使用されるため、無視してください)。
電話番号はアクティブなデバイスに対して一意である必要があるため、DeviceIDおよびIsArchivedフラグのインデックスを伝達する必要があったPhoneサブタイプテーブルに注意してください。他のサブタイプテーブルでもこれを行う必要があります。これが良いデザインか悪いデザインかはわかりません。
この部分は本当に私を混乱させます...
外部キー値を削除済みとしてマークできるソフト削除を処理するためのベストプラクティスは何ですか。考えられる唯一のことは、削除されたデータに関連するすべてのレコードを検索するルーチンを作成し、矛盾を解決するためのレポートをユーザーに作成することです。たとえば、場所のテーブルがデバイステーブルに関連付けられていて、一部の場所が一時的に削除されている場合、デバイスは存在しなくなったため移動する必要がある場所を参照しています。
ちなみに、私はMS SQL Server 2008 R2を使用しており、アプリケーションでEntity Framework 4を使用する予定です。パフォーマンスよりもデータベースの保守性を重視します。
読んでくれてありがとう。
ユーザーがアーカイブデータをクエリする必要がある場合は、bit
フラグまたはsoft delete
の方が簡単です。ユーザーがデータを必要としなくなった場合は、アーカイブテーブルを使用します。
上記のあなたの説明に基づいて、私はSoft Delete
バージョン。私たちのシステムの1つの経験から、私は古いデータを移動するためにアーカイブスキーマを使用しましたが、ユーザーがデータにアクセスする必要があるため、問題につながるだけでした。したがって、UNION ALL
実行する必要のあるすべてのクエリ。
問題の結果、そのルートを停止して、はるかに簡単なソフト削除に移行しました。
必要なすべてのテーブルにbit
フラグを追加し、データをクエリするときにこれをWHERE
句に含めました。
データをINSERT
するとき、このフィールドにデフォルト値があることを確認することをお勧めします。 IsArchived
を使用している場合、すぐにアーカイブしたくないため、列のデフォルト値はfalseになります。
最近、私はソフト削除とアーカイブテーブルの問題に取り組んでいます。明らかに、「ソフト削除しないでアーカイブする」という記事がウェブ上にたくさんあります。私はまだあなたの問題が存在することを認めるアーカイブ擁護者を見つけていませんが、私はその理由を理解したと思います。
問題なのは、テーブルが外部キーのPKエンドである可能性がある理由が2つあるということです。それは、他のテーブルのデータを論理的に所有している、または参照しているためです。 OrderはOrderDetailsを「所有」します。アドレスは単に州を参照します。
テーブルを参照するすべてのFKが "所有者"の関係にある場合は、一時的に削除しないでください。
DeviceTypesは、Devicesによって所有されているのではなく、参照されています。アーカイブパターンはここでは機能しません。参照整合性を強制するのに邪魔になります。
ただし、次のことが言えます。DeviceTypeの中止は、論理的には削除ではありません。データは、デバイスから参照されるという意味でまだ生きています。使用中のDeviceTypeを(論理的に)削除することはできません。したがって、論理操作は削除ではないため、NotAvailableフラグの使用は実際には一時的な削除ではありません。これが、アーカイブ擁護者がそれに取り組んでいない理由だと思います。
データの論理的な削除は行いたいが、監査目的でのみ保持するため、アーカイブテーブルを使用しました。私の選択の背後にある理由は、実際にはデータベースとは何の関係もありませんでした。それは、EntityFrameworkがソフト削除を適切にサポートしていないため、ナビゲーションプロパティにそれらを適用する適切な方法が見つからなかったためです。
SQL Server 2008 R2では、アーカイブの擁護者がソフト削除にあると主張するデメリットのほとんどを軽減できます。フィルター選択されたインデックスを使用して、テーブルに削除されたレコードの束を運ぶことによるパフォーマンスのペナルティを減らすことができます(そして、バックアップ戦略に意味のあるテーブルをパーティション化しない限り、ソフト削除の動作はアーカイブの動作よりもはるかに安価です) )。削除フラグにも参照整合性を適用できると思います Celkoの記事 で見た手法を借りて、子テーブルには、ParentIsDeletedフラグと2つのFKを親に割り当てることができます。 ParentId、ParentId、ParentIsDeletedのもう1つ。また、ParentIsDeleted、SelfIsDeletedを設定し、IsDeletedを永続的な計算フィールドにすることで、undeleteが子の直接削除と親からカスケードされた削除を区別できるようにすることもできます。ただし、実際には削除するのではなく、デバイスが存在するDeviceTypeが使用できないことを防止またはカスケードする必要はありません。
プライマリIDとIsArchivedフラグの組み合わせでキーテーブルを分割できます。これには、クエリを簡単にし、アーカイブされていないレコードに対するクエリのパフォーマンスなどを維持するという二重の利点があります。