2

それは議論のためだけの質問です。現在、mysql データベース テーブルを再設計する必要があります。基本的に、このテーブルには、別のデータベースから同期したすべての契約レコードが含まれています。契約レコードは、変更、削除、またはユーザーが GUI インターフェイスを介して新しい契約レコードを追加できます。この段階では、テーブル構造は契約情報とまったく同じです (列: シリアル番号、有効期限など)。その場合、テーブル全体を同期することしかできません (古いレコードをすべて削除し、新しいレコードに置き換えます)。テーブルを差分 (変更、新規、削除されたレコードとのみ同期) 同期したい場合、データベース スキーマをどのように変更すればよいですか?

これが私が思いついた方法ですが、データベース アプリケーションでは一般的なシナリオだと思うので、提案が必要です。1) シーケンス番号の概念/列を導入する: 各シーケンスについて、新しく追加されたレコード、変更されたレコード、削除されたレコードをこのシーケンス番号でマークします。最後に同期されたシーケンス番号を記録することにより、より高いシーケンス番号を持つレコードのみを渡します。

2) 削除されたコントラクトは元に戻すことができ、元のテーブルには主キー制約があるため、削除されたレコード用に別のテーブルを作成する必要がありますか? または、この契約が削除されたかどうかを示すフラグ列を追加しますか?

私の質問を明確に説明していただければ幸いです。とにかく、これに関する記事や独自の提案を知っている場合は、お知らせください。ありがとう!

4

1 に答える 1

9

デルタの概念と混同していると思います。

全ロード (データセット全体) または変更のみ (「デルタ」) を受け取ります。

全負荷を扱う場合は、切り捨て+挿入を行うことができます。そうすれば、新しい行と古い行または削除を処理する必要がなくなります。これは、参照整合性の制約などのために実行できない場合があります。

デルタを受け取った場合、各行は通常、次の 2 つのカテゴリのうちの 1 つに分類されます。

  1. 一致するキー = UPDATE. 同一データの行を無視するか、上書きするかを選択できます。
  2. 一致するキーがありません =INSERT

削除は特別です。存在しない行は送信できません。したがって、それをどのように扱うべきかについて合意する必要があります。フル ロードの場合、受信したデータ セットに存在しないすべてのローカル行を削除できます。

デルタの場合、削除マーカー (フラグ、日付) を含む行を送信することに同意できます。次に、行を削除マーカーで保持するか (上記の (1) によって自動的に処理されます)、または行を保持するかを決定できDELETEます。遅かれ早かれ誰かが行の欠落/データ品質の悪さを非難し、DELETE_DATEを彼らの顔に投げつけるので、私はそれを維持することをお勧めします.

MySQL の場合、INSERT ... ON DUPLICATE KEY UPDATEを使用して「アップサート」機能を実装できます。

より具体的なヘルプが必要な場合は、詳細を提供する必要があります。

アップデート:

わかりました、ここに例があります。次のテーブル構造があるとします。

create table contracts(
   contract_id int         not null
  ,details1    varchar(20)
  ,details2    varchar(20)
  ,delete_date date
  ,primary key(contract_id)
);

更新された行を受け取るたびに、それらを同じ構造の一時テーブルに挿入します。

create table contracts_delta(
   contract_id int         not null
  ,details1    varchar(20)
  ,details2    varchar(20)
  ,delete_date date
  ,primary key(contract_id)
);

いくつかのサンプルデータ:

mysql> select * from contracts;
+-------------+----------+----------+-------------+
| contract_id | details1 | details2 | delete_date |
+-------------+----------+----------+-------------+
|           1 | a1       | a2       | NULL        |
|           2 | b1       | b2       | NULL        |
|           3 | c1       | c2       | 2011-01-03  |
+-------------+----------+----------+-------------+

mysql> select * from contracts_delta;
+-------------+----------+----------+-------------+
| contract_id | details1 | details2 | delete_date |
+-------------+----------+----------+-------------+
|           2 | b1       | b2       | 2011-01-03  | <-- Row was deleted
|           3 | c1       | c2       | NULL        | <-- No longer deleted
|           4 | d1       | d2       | NULL        | <-- This is new row
+-------------+----------+----------+-------------+

Using the syntax I linked to earlier, you can insert all new rows. Whenever the row is already there (on duplicate) we chose to update the columns instead. Note that this handles deleted rows automatically since the delete_date is a regular column like everything else.

insert 
  into contracts(
        contract_id
       ,details1
       ,details2
       ,delete_date
       )
 select contract_id
       ,details1
       ,details2
       ,delete_date
  from contracts_delta s
    on duplicate key 
    update contracts.details1    = s.details1
          ,contracts.details2    = s.details2
          ,contracts.delete_date = s.delete_date;

After the "upsert", the data in contracts will look like this:

mysql> select * from contracts;
+-------------+----------+----------+-------------+
| contract_id | details1 | details2 | delete_date |
+-------------+----------+----------+-------------+
|           1 | a1       | a2       | NULL        |
|           2 | b1       | b2       | 2011-01-03  |
|           3 | c1       | c2       | NULL        |
|           4 | d1       | d2       | NULL        |
+-------------+----------+----------+-------------+

-- At this point you can choose to drop the delta table (remember to re-create it next time)

drop table contracts_delta;

-- Or you can just truncate it to save some space. (You need to make sure it's empty on the next load anyway)

truncate table contracts_delta;

-- Or you can save the actual delta (rename the table) incase you need the individual deltas sometime

alter table contracts_delta rename to contracts_delta_20110115;
于 2011-01-13T22:32:21.173 に答える