データベースの同期およびソフト削除シナリオでの廃棄テーブルと削除済みフラグ


17

クライアントの同期の必要性のために、削除されたアイテムを追跡する必要があります。

一般に、トゥームストーンテーブルと、サーバーデータベースから行が削除されたときを追跡するトリガーを追加する方が基本ですか?元のテーブルを削除し、通常はビット型の列で削除済みとしてフラグを立てて、行が削除されたことと、削除が発生したときに追跡する別の列を示しますか?

回答:


17

一般に、特定の要件を把握し、ほとんどの状況で最適に機能するものに基づいて設計上の決定を下すことをお勧めします。 どちらかが望ましいでしょう。収集するいくつかの詳細を次に示します。

  • 削除にはどれくらいの速さが必要ですか?
  • 元に戻すにはどれくらいの速さが必要ですか?
  • 削除されたデータはどれくらいの頻度で照会され、削除されていないデータで照会されますか?
  • 削除されたデータのクエリはどれくらい速くする必要がありますか?
  • 削除されたアイテムまたは変更のみを保存する必要がありますか?
  • プライマリテーブルのテーブル/インデックスを小さく保つ必要がありますか?
  • データベースプラットフォームで利用可能なパーティション分割および/または変更追跡技術は何ですか?
  • 利用可能なディスク容量は?
  • 削除はオンザフライで実行されますか、それともバッチ処理で実行されますか?

異なるシステム要件間のトレードオフの問題だと思います。高速削除/削除解除が必要な場合は、フラグをお勧めしますが、削除されたアイテムとプライマリテーブルで高速クエリが必要な場合、およびあらゆる種類の変更を追跡する必要がある場合、トゥームストーンアプローチはより良い。
ロレンツォポリドリ

了解しました。別のオプションが望ましい場合もあります。たとえば、ソフト削除を24時間のみ使用可能にする必要がある場合、Oracleでは、保証されたUNDO保存期間を設定し、フラッシュバッククエリを使用して削除されたデータを表示することを検討できます。
リーリッフェル

5

たぶん、2つの方法を意図的に組み合わせる必要があります。なぜ ???

そのテーブルを使用しましょう(MySQL-dialect)

CREATE TABLE mydata
(
    id int not null auto_increment
    firstname varchar(16) not null,
    lastname varchar(16) not null,
    zipcode char(5) not null,
    ...
    deleted tinyint not null default 0
    KEY (deleted,id),
    KEY (deleted,lastname,firstname,id),
    KEY (deleted,zipcode,id),
    KEY (lastname,firstname),
    KEY (zipcode),
    PRIMARY KEY (id)
);

PRIMARY KEYを除き、作成するすべてのインデックスの前にdeletedフラグを付け、最後にid

トゥームストーンテーブルを作成しましょう

CREATE TABLE mytomb SELECT id FROM mydata WHERE 1=2;
ALTER TABLE mytomb ADD PRIMARY KEY (id);

テーブルに既にdeletedフラグがある場合は、tomstoneテーブルにデータを入力できます

INSERT INTO mytomb SELECT id FROM mydata WHERE deleted = 1;

これで、データとトゥームストーンが準備されました。削除はどのように実行しますか?

07305郵便番号のすべての人を削除するとします。次を実行します。

INSERT IGNORE INTO mytomb SELECT id FROM mydata WHERE deleted=0 AND zipcode='07305';
UPDATE mydata SET deleted=1 WHERE deleted=0 AND zipcode='07305';

わかりました。これは、見方を問わず、多くのオーバーヘッドのようです。

ここで、削除されたすべてのデータを表示しますか?以下に2つの異なる方法を示します。

  • SELECT * FROM mydata WHERE deleted=1;
  • SELECT B.* FROM mytomb A INNER JOIN mydata B USING (id);

mytombのidの数がmydataのrowcountの5%を超える場合、全テーブルスキャンです。それ以外の場合、各行のルックアップを使用したインデックススキャン。これらの点でベンチマークに注意してください。説明計画を検索します。

さて、郵便番号07304のすべての人を見たいですか?以下に2つの異なる方法を示します。

  • SELECT * FROM mydata WHERE deleted=1 AND zipcode='07304';
  • SELECT A.* FROM mydata A LEFT JOIN mytomb B USING (id) WHERE B.id IS NULL AND A.zipcode='07304'

一括削除はどうですか?以下に2つの異なる方法を示します。

  • DELETE FROM mydata WHERE deleted=1;
  • DELETE B.* FROM mytomb A INNER JOIN mydata B USING (id); DELETE FROM mytomb;

結論

今、私は両方の方法を維持することを言っているのではありません。時間をかけてこれを行うと、全体的な操作性の点でどのメソッドが高速であるかがわかります。ライブデータのクエリ、削除されたデータのクエリ、および大量削除のベンチマークを最適に決定する必要があります。


両方の手法を継続的に使用することに利点はありますか?または、パフォーマンスを評価するためにそれらを並行して使用し、一方または他方にコミットすることを提案していますか?
すべての取引のジョン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.