2011-01-13 22 views
2

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

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

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

質問を明確に説明してください。とにかく、あなたがこれに関する記事や自分の提案を知っているなら、私に知らせてください。ありがとう!

答えて

8

デルタのコンセプトと混同していると思います。

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

フルロードを処理する場合は、トランケート+挿入を行うことができます。そうすれば、新旧の行や削除を処理する必要がなくなります。これは、参照整合性制約などで実現可能ではないかもしれない

あなたがデルタを受け取った場合、各行は、通常1〜2のカテゴリーに入れられる:

  1. マッチングキー= UPDATE。同じデータを持つ行を無視するか、上書きすることができます。
  2. 一致キー= INSERT

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

デルタの場合、削除マーカー(フラグ、日付)を含む行を送信することに同意することができます。次に、削除マーカー(上記の(1)によって自動的に処理されます)を使用して行を保持するか、DELETE行を保持するかを決定することができます。遅かれ早かれ誰かが行の不足/悪いデータの品質を告発し、DELETE_DATEを自分の顔に投げ捨てるので、それを残しておくことをお勧めします。

MySQLの場合、INSERT ... ON DUPLICATE KEY UPDATEを使用して "upsert"機能を実装できます。

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

更新:

[OK]を、ここでの例です。あなたは、次のテーブル構造を持っていることを言う:

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 
+-------------+----------+----------+-------------+ 

以前にリンクした構文を使用すると、すべての新しい行を挿入できます。行がすでに存在するときは(重複して)、代わりに列を更新することを選択しました。 delete_dateは他のすべてと同様に通常のカラムなので、これは自動的に削除された行を処理することに注意してください。 「アップサート」の後

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; 

、契約内のデータは次のようになります。

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  | 
+-------------+----------+----------+-------------+ 

- この時点では、デルタテーブルを削除するかを選択できます(次のそれを再作成することを忘れないでください時間)

- または一部の領域を節約するために切り捨てることができます。 、いつか

alter table contracts_delta rename to contracts_delta_20110115; 
+0

おかげか、あなたは、個々のデルタを必要包み、実際のデルタ(テーブルの名前を変更)を保存することができます -

truncate table contracts_delta; 

(あなたはそれがとにかく次のロードに空のを確認する必要があります)ロニス。私は主にデルタケースに対処する方法を知りたい:1)更新行の場合、mysqlは正確な値が変更されているかどうかについてはあまり正確ではないようだ。同じ値で行を更新しても、影響を受ける行番号はまだ1/2です。 2)削除された行については、もちろん、私は行を永久に削除しません。しかし、私はそれらをアーカイブテーブルに削除するか、削除されたフラグを同じテーブルに入れるのが良いかどうかはわかりません。 – WilliamLou

+0

@ロンニス:特にレコードを削除するソリューションを探しています。あるプロジェクトでは、削除フラグを使用しています。しかし、列に固有の制約があり、その固有の制約に違反する新しいレコードを作成したい場合はどうでしょうか。その場合、データを完全に削除する方がよいでしょう。しかし、クライアントは削除についてどのように通知されますか?私はIDを保存し、削除されたレコードの日付を削除するための2番目のテーブルを作成することを想像することができます。特別なテーブルを持たないソリューションはより良いでしょう。助言がありますか? – Konsumierer

関連する問題