データ統合のタスクが登場して以来、システム間でのプログラム的な同期の必要性がしばしば取り上げられています。実際に変更された行のみを更新し、リソースを節約し、ロックを最小限に抑える必要があります。過去の標準的なアプローチは完全な置き換えや手動での差異検索であり、余分な操作を消費し、エラーを引き起こすことがあります。
問題:同期する際には、すべてのデータではなく、変更されたデータのみを検出して更新する必要があります。これは、特に大量のデータや分散データベースにおいて、パフォーマンス、ネットワークトラフィック、整合性の観点から重要です。
解決策:通常、元のテーブルとターゲットテーブルをJOIN演算子を用いて比較し、HASHやチェックサムを使用して差異を計算し、MERGE(またはUPSERT)や特別なトリガーを使用して「不一致」な行のみを更新します。
SQL Serverのコード例:
MERGE target_table AS t USING source_table AS s ON t.id = s.id WHEN MATCHED AND (t.name <> s.name OR t.value <> s.value) THEN UPDATE SET t.name = s.name, t.value = s.value WHEN NOT MATCHED BY TARGET THEN INSERT (id, name, value) VALUES (s.id, s.name, s.value);
主な特徴:
常にMERGEは同時更新時の競合を防ぐか?
いいえ、追加のトランザクション制御がない場合、競合(レースコンディション)が発生する可能性があります。最大の正確性を確保するために、適切なトランザクションの隔離レベルを使用してください。
複雑な同期にMERGEの代わりにUPDATE ... JOINを使用できますか?
しばしば可能ですが、そのアプローチではターゲットテーブルに新しい行を追加することはできません。MERGE/UPSERTのみが更新と追加を行います。
UPDATE t SET t.name = s.name, t.value = s.value FROM target_table t JOIN source_table s ON t.id = s.id WHERE t.name <> s.name OR t.value <> s.value;
同期されるテーブルが異なる列のセットを持つ場合はどうすればよいですか?
対応するフィールドを明示的に列挙し、「常にすべての」フィールドを更新しようとしないことをお勧めします。必要に応じてマッピングテーブルや変換を使用してください。
ETLエンジニアがキーによるすべてのレコードを単純なUPDATEで「ロード」します:テーブルは数千万行あり、プロセスは数時間かかり、サーバーをブロックします。新しい行の挿入がなく、新しいデータが失われます。
利点:
欠点:
専門家はロード前に行のチェックサムを計算し、変更されたレコードをフィルタリングし、MERGEを使用して迅速に同期し、新しい行を追加します。プロセスは数分で行われ、過負荷はありません。
利点:
欠点: