Person
オブジェクトがあるとします。このPerson
オブジェクトには、name
、address
、accountNumber
などの多くのフィールドがあります。
今の私の要件は、特定の時点での任意の個人の状態を提供するように求められた場合に「再構築」/「フェッチ」できるように、各個人の複数のバージョンを維持することです。その状態。
例として、t0
address1
がpersonA
に関連付けられていたとしましょう。そして、t1
(t1
> 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
を使用しました。
これがリレーショナルデータの「問題」であることを正しく認識したとおり、関連するエントリを変更すると履歴が変更されます。
問題は、アイデンティティを保持する方法ですか?
あなたが持っている典型的なeコマースシナリオがあるとしましょう
したがって、identityが保持される必要があります。
Martha Miller
が発行され、Order 12345
が発行され、123456789 Nike shoes
が注文されました
そしてこれidentityは保存されなければなりません、
Martha Miller
が後で結婚し、それ以降Martha Smith
と呼ばれる場合でもNew York
からLos Angeles
に移動しました123456789
がNike shirts
ではなくNike shoes
に使用されるようになりました。モデリング戦略の1つは、同一顧客に対して複数の表現を使用することです。
id 1
のある住所はMartha Miller
であり、id 12345
のある住所は同じ人物ですが、現在はMartha Smith
と呼ばれ、顧客は同じaddress_customer_id
を介して参照されます。 af5aa5df-ad4b-42fa-97ed-e25e8cad1962
customer
は複数のアドレスエントリを持つことができます。また、アドレスが変更されるたびに、顧客のアドレステーブルに新しいエントリが存在します。また、アドレスが変更されない限り、現在のアドレスが使用されます。変更後は、新しいものが使用され、前のものが保持されます。したがって、各時点で、このデータを持つこの顧客はこの注文を行ったのアイデンティティが1つだけあります。
それは同じです。アイテムについて。
別の戦略は、単に非正規化です。これは履歴データであり、読み取るだけなので、通常はデータを正規化することを回避するための異常に直面することはありません。
次に、JSON
を最新のほとんどのRDBMSsesのデータ型として活用できる可能性があります。これにより、注文全体をdocument
として保存するなど、他の優れたオプションが可能になります。
優れた Thomasの回答 に加えて、このニーズをサポートするネイティブDBMSソリューションがあることを追加したいと思います。 。
DBMSが一時データをサポートしていない場合は、ニーズを詳しく調べ、時間依存データの管理を区別することにも興味があるかもしれませんおよび履歴データの監査証跡を保証します。
一部のRDBMSは、想像どおりに、完全に時間依存のデータをネイティブでサポートしています。 SQLの世界では、 ANSI SQL 2011 により、システムバージョンのテンポラルテーブルが導入されました。
一部のデータは一定期間有効であることがわかっています。使用される値は関連する日付に依存することがわかっています。典型的な例は、人の住所や製品の価格です。一般に、新しい値には明確な開始日があります。
その後、次のことができます。
歴史的データは異なるニーズに対応しています。これは、永続的であると想定されているが、例外的な理由で変更される可能性があるデータ用です。したがって、主に現在の有効な値に関心があります。例外的に、私たちは歴史的な価値に関心があります(たとえば、監査目的、または法的問題)。
たとえば、生年月日などです。一般に、変更することは想定されていません。ただし、事務的なエラーにより、この日付が後で修正される場合があります。この日付を使用して年齢ベースのコンテンツへのアクセスを許可した場合(例: PG13 games )、訴訟の場合にそのような変更を追跡できると便利です。
これは次のように実装できます。