web-dev-qa-db-ja.com

データベース設計-オブジェクトのバージョンの維持

Personオブジェクトがあるとします。このPersonオブジェクトには、nameaddressaccountNumberなどの多くのフィールドがあります。

今の私の要件は、特定の時点での任意の個人の状態を提供するように求められた場合に「再構築」/「フェッチ」できるように、各個人の複数のバージョンを維持することです。その状態。

例として、t0address1personAに関連付けられていたとしましょう。そして、t1t1> t0)で、この人物のアドレスがaddress2に変更されます。次に、これらの両方の情報を保存する必要があります。私のビジネスニーズは、いつでもその人の住所を尋ねられるtです。ここで、tは次のいずれかです。

  • t <t0(この場合、アドレスは存在しません)
  • t0 <t <t1(この場合、アドレスはaddress1
  • t> t1(この場合、アドレスはaddress2

これをデータベースでモデル化したいと思います。

テンポラルテーブルは私のビジネスニーズであり、テンポラルはレポートと監査の目的で使用されるため、使用したくありません。 (または最悪の場合、問題をデバッグします)

私は物事をシンプルに保ちたいと思っています。そのため、最小の変更の場合でも完全なPersonオブジェクトをDBに挿入しています。

私のpersonテーブルは次のようになります。

| person_id | name    | address        | phone_number | account_number | start | end |
| --------- + ------- + -------------- + ------------ + -------------- + ----- + --- | 
| 1         | personA | address text 1 | 123456789    | 741852963      | t0    | t1  |
| 1         | personA | address text 2 | 123456789    | 741852963      | t1    | -   |

この場合のperson_idはこのテーブルで一意ではないことに注意してください(したがって、このテーブルの主キーにすることはできません)。1人のユーザーが複数の編集を行うことができるため、同じperson_id繰り返すことができます。

私のビジネスケースは、startおよびendを使用してperson_id 1の実際の行の有効性をチェックすることで識別できる方法で解決されています。

私が直面している問題は、他のテーブルの参照キーとしてperson_idを使用できることです。どちらにしますか。

personテーブルのすべての行を一意に決定し、このテーブルの主キーおよび他のテーブルの参照キーとして使用できる一意の自動インクリメンタル列を追加できます(row_idなど)。他のすべてのテーブルがこのテーブルを参照して、2つのrow_idが同じperson_idに対応しているかどうかを確認する必要があるため、これを行いたくありません。

私の頭に浮かぶ1つの解決策は、単一の列を持ち、個人の一意のIDを格納するだけの個別のテーブルperson_unique_idsを用意できることです。 personテーブルにはperson_idが含まれます。これはperson_unique_ids.person_idへの参照になります。これにより、他のテーブルでもこの​​IDを使用できます。他のテーブルで伝達されます。

しかし、上記の解決策は、新しい人を挿入するとき、最初にperson_unique_idsにエントリを挿入し、新しく挿入されたエントリを取得し、これを使用してメインpersonに挿入する必要があることを示唆しています。実際にすべてのデータを保持します。

これは並行性の問題につながり、ボトルネックになっている完全な挿入を同期することを余儀なくされています。

別のテーブルがなくても、すべての履歴データを解決できるこの問題へのアプローチを誰かが提案できますか?

実際の使用例では、personオブジェクトがないことに注意してください。むしろその方法は複雑すぎるオブジェクトです。私は、ユースケースを模倣するためだけにPersonを使用しました。

3
Lavish Kothari

これがリレーショナルデータの「問題」であることを正しく認識したとおり、関連するエントリを変更すると履歴が変更されます。

問題は、アイデンティティを保持する方法ですか?

あなたが持っている典型的なeコマースシナリオがあるとしましょう

  • 顧客
  • オーダー
  • 注文のアイテム

したがって、identityが保持される必要があります。

Martha Millerが発行され、Order 12345が発行され、123456789 Nike shoesが注文されました

そしてこれidentityは保存されなければなりません、

  • Martha Millerが後で結婚し、それ以降Martha Smithと呼ばれる場合でも
  • New YorkからLos Angelesに移動しました
  • また、アイテム123456789Nike shirtsではなくNike shoesに使用されるようになりました。

モデリング戦略の1つは、同一顧客に対して複数の表現を使用することです。

id 1のある住所はMartha Millerであり、id 12345のある住所は同じ人物ですが、現在はMartha Smithと呼ばれ、顧客は同じaddress_customer_idを介して参照されます。 af5aa5df-ad4b-42fa-97ed-e25e8cad1962customerは複数のアドレスエントリを持つことができます。また、アドレスが変更されるたびに、顧客のアドレステーブルに新しいエントリが存在します。また、アドレスが変更されない限り、現在のアドレスが使用されます。変更後は、新しいものが使用され、前のものが保持されます。したがって、各時点で、このデータを持つこの顧客はこの注文を行ったのアイデンティティが1つだけあります。

それは同じです。アイテムについて。

別の戦略は、単に非正規化です。これは履歴データであり、読み取るだけなので、通常はデータを正規化することを回避するための異常に直面することはありません。

次に、JSONを最新のほとんどのRDBMSsesのデータ型として活用できる可能性があります。これにより、注文全体をdocumentとして保存するなど、他の優れたオプションが可能になります。

3
Thomas Junk

優れた Thomasの回答 に加えて、このニーズをサポートするネイティブDBMSソリューションがあることを追加したいと思います。 。

DBMSが一時データをサポートしていない場合は、ニーズを詳しく調べ、時間依存データの管理を区別することにも興味があるかもしれませんおよび履歴データ監査証跡を保証します。

ネイティブ実装技術

一部のRDBMSは、想像どおりに、完全に時間依存のデータをネイティブでサポートしています。 SQLの世界では、 ANSI SQL 2011 により、システムバージョンのテンポラルテーブルが導入されました。

時間依存データ

一部のデータは一定期間有効であることがわかっています。使用される値は関連する日付に依存することがわかっています。典型的な例は、人の住所や製品の価格です。一般に、新しい値には明確な開始日があります。

その後、次のことができます。

  • 時間に依存しないデータの主要なエンティティがあります。極端なケースは、主キーのみを持つことです(レコードの作成日である場合もあります)。
  • 時間依存データ用の別個のエンティティーがあります。キーは、メインエンティティの主キーと開始日になります。 null可能な終了日は、現在の値を簡単に見つけるために使用できます
  • 時々、よく見るとグループの背後にある個別のエンティティを識別できますod data。通常、アドレスは目的(例:通信、配信、請求書)と独自の有効期間。

歴史的データ

歴史的データは異なるニーズに対応しています。これは、永続的であると想定されているが、例外的な理由で変更される可能性があるデータ用です。したがって、主に現在の有効な値に関心があります。例外的に、私たちは歴史的な価値に関心があります(たとえば、監査目的、または法的問題)。

たとえば、生年月日などです。一般に、変更することは想定されていません。ただし、事務的なエラーにより、この日付が後で修正される場合があります。この日付を使用して年齢ベースのコンテンツへのアクセスを許可した場合(例: PG13 games )、訴訟の場合にそのような変更を追跡できると便利です。

これは次のように実装できます。

  • ユーザーがアクセスできる完全なデータは時間に依存すると見なされます(1の解決策を参照)。デフォルトでは、クエリは空の終了日を探します。利点は、以前のバージョンを簡単に参照できることです。
  • 完全なデータは、時間に依存しない永続的なものと見なされますが、履歴値が必要な場合に備えて、個別のテーブルを使用して履歴値をアーカイブします。時間に依存する醜い(しかし便利な)クローンテーブルになる可能性があります。また、フィールド名、新旧の値、変更の日付、変更を行ったユーザー(全世界ERPマーケットリーダーは、この手法を使用して重要なフィールドへの変更を記録します。変更ヘッダーを使用して、ユーザーと変更日、およびテーブル名、フィールド名、変更されたデータを含むいくつかの関連する変更項目を記録します)
0
Christophe