リビジョン履歴を維持するための DB 設計における一般的な戦略は何ですか? 私が扱っていたのが1つのテーブルだけであれば、それほど難しくはないと思います. 各更新を新しいレコードとしてテーブルに保存するだけです。最後のレコードは常に最新のリビジョンになります。
しかし、データが複数のテーブルにまたがって格納されている場合、リビジョンを追跡できるように設計するにはどのような方法がよいでしょうか?
リビジョン履歴を維持するための DB 設計における一般的な戦略は何ですか? 私が扱っていたのが1つのテーブルだけであれば、それほど難しくはないと思います. 各更新を新しいレコードとしてテーブルに保存するだけです。最後のレコードは常に最新のリビジョンになります。
しかし、データが複数のテーブルにまたがって格納されている場合、リビジョンを追跡できるように設計するにはどのような方法がよいでしょうか?
バージョン管理されたテーブルごとに履歴テーブルを追加することを好みます。time_from
およびtime_to
追加のフィールドを持つメイン テーブルと同じ構造。トリガーで透明に満たされます。time_to
遠い未来に設定された最新のリビジョンの。
指定した瞬間の状態は、次のようなクエリで取得できます。
SELECT * FROM user_history
WHERE time_from >= '2012-02-01' AND time_to <= '2012-02-01'
私にとっては、現在のデータを取得または結合するときに複雑な条件が必要になるため、メイン テーブル内に履歴を保存することは一般的には良い考えではありません。
難しいのは、「ベース」テーブルのバージョン管理ではありません。単一のテーブルを分離する場合と同様に、個別にバージョン管理するだけです。
難しいのは、それらの間の接続を追跡することです。
それをどの程度正確に行うかは、特定のプロジェクトの要件によって異なります。以下は、販売注文を「履歴化」する方法の例ですが、他にも多くのバリエーションが考えられます。
データ差分。API を利用した DB リビジョン追跡。
完全開示:
私はDatadiffを構築しました。SASS 製品をサポートするために、MongoDB のデータ モデルの視覚的な履歴を提供するソリューションが必要でした。SQL データベースでも動作します。
key:val
表記法を使用して基本的なクエリを実行できます。すなわちid:123
MySQL のバイナリ ロギングをオンにして、それをそのまま使用します。
私が扱っている各オブジェクトには、少なくとも1つのいわゆるインスタンステーブルがあり、時間の経過とともに変化する傾向があるデータを保持するアプローチを使用しています。通常、このようなテーブルは次の概念に従います。
_HISTORY
サフィックスがあります。start_dt
ありend_dt
、オブジェクト インスタンスの有効期間を示します。start_dt
is NOT NULL
、end_dt
can be NULL
、インスタンスが最新であり、その時間に制限されていないことを示します。1/Jan-2013
に設定し、 で新しいレコードを挿入する必要があります。end_dt
31/Dec-2012 23:59:59
start_dt
1/Jan-2013 00:00:00
revision
リビジョンを追跡する必要がある場合は、フィールドを追加することもあります。このような設計で適切な RI 制約を設定するために、バージョン管理されたオブジェクト用に常に 2 つのテーブルを用意しています。オブジェクトについてCustomer
、次のテーブルセットがあるとします。
customer (customer_id INTEGER, PRIMARY KEY (customer_id));
customer_history (customer_id INTEGER, start_dt TIMESTAMP, end_dt TIMESTAMP,
name VARCHAR(50), sex CHAR(1), ...,
PRIMARY KEY (customer_id, start_dt));
customer_bank_history (customer_id INTEGER, start_dt TIMESTAMP, end_dt TIMESTAMP,
bank_id INTEGER, iban VARCHAR(34));
他のすべての場所ではcustomer(customer_id)
、外部キーを構築するために使用します。実際の顧客の詳細を照会するのは簡単です。
SELECT c.customer_id, ch.name, ch.sex
FROM customer c
JOIN customer_history ch ON c.customer_id = ch.customer_id
AND now() BETWEEN ch.start_dt AND coalesce(end_dt, now());
私がそのようなデザインを好む理由:
これがあなたを助けることを願っています。