web-dev-qa-db-ja.com

エンティティ属性値(EAV)の代替?

私たちのデータベースは、EAV(Entity-Attribute-Value)モデルに基づいて設計されています。 EAVモデルを使用したことがある人は、柔軟性の目的で付属するがらくたをすべて知っています。

EAVモデル(柔軟性)を使用する理由をクライアントに尋ねました。その理由は次のとおりです。エンティティは時間とともに変化します。そのため、今日はいくつかの属性を持つテーブルがあるかもしれませんが、1か月以内にいくつかの新しい属性が追加されるか、既存の属性の名前が変更される可能性があります。彼らは、レポートを作成して任意の段階に戻り、その段階のエンティティの形状に基づいてデータをクエリする必要があります。

これは従来のリレーショナルモデルでは実現できないことを理解していますが、個人的にはEAVをアンチパターンと見なしています。エンティティとインスタンスへの変更の時間ディメンションをキャプチャできるようにする他の代替モデルはありますか?

乾杯、モッシュ

48
Mosh

EAVが忠実に行われたか、または不適切に行われたかには違いがあります。 5NFは熟練した人々または無知な人々によって行われました。

6番目の正規形は既約正規形です(これ以上正規化できません)。ヌル問題などの一般的な問題の多くを排除し、欠損値を特定する究極の方法を提供します。それは学問的および技術的に堅牢なNFです。これをサポートする製品はなく、一般的には使用されていません。適切かつ一貫して実装するには、メタデータを実装するためのカタログが必要です。もちろん、ナビゲートに必要なSQLはさらに面倒になります(SQLは既に面倒な再結合です)が、これはメタデータからのSQLの生成を自動化することで簡単に克服できます。

EAVは6NFの部分セットまたはサブセットです。問題は、通常、(DDLを変更せずに列を追加できるようにするために)目的で行われ、6NFを知らない人や、メタデータを実装しない人によって行われます。ポイントは、原則と概念としての6NFとEAVが実質的な利点を提供し、パフォーマンスが向上することです。しかし、一般的には適切に実装されておらず、その利点は実現されていません。 EAVが悪いためではなく、実装が貧弱であるために、かなりの数のEAV実装が災害です。

例えば。 6NF/EAVデータベースから3NF行を構築するために必要なSQLは複雑であると考える人もいます。いいえ、煩雑ですが複雑ではありません。さらに重要なのは、通常のSQL VIEWを提供できるため、すべてのユーザーとレポートツールが3NF VIEWのみを表示し、6NF/EAVの問題が透過的に見えるようにすることです。最後に、必要なSQLは自動化できるため、多くの人が耐える人件費はまったく不要です。

したがって、答えは、実際には、EAVの父であり、より純粋なフォームであるシックスノーマルフォームが、その代わりです。警告は、それが適切に行われていることを確認します。私は1つの大きな6NF dbを持っており、人々が投稿した問題に苦しむことはなく、それは美しく実行され、顧客は非常に満足しています(これ以上の作業は完全な機能的満足の兆候ではありません)。

私はすでに、あなたの質問にも当てはまる別の質問への非常に詳細な回答を投稿しました。

その他のEAV質問

51
PerformanceDBA

使用するリレーショナルモデルの種類に関係なく、フィールド名の変更を追跡するには、トランザクションログまたは監査テーブルで追跡する必要のある大量のメタデータが必要です。残念ながら、特定の日付のいずれかの状態のクエリは非常に複雑です。ただし、クライアントが特定の日付の状態のみを必要とする場合、つまり名前の変更だけでなく、状態全体を必要とする場合は、データベースを複製してトランザクションログを必要な特定の時間にロールバックし、新しいインスタンスでクエリを実行できます。 。ただし、指定した日付の後に追加されたエンティティを古いフィールド名でクエリに表示する必要がある場合は、非常に大きなエンジニアリング上の問題が発生しています。その場合、質問で提供された情報を使用して、クライアントと代替案を交渉するか、代替ソリューションを見つけるためのレポートの使用に関する詳細情報を入手することをお勧めします。

ドキュメントベースのデータストアに移動することもできますが、それでも2番目のケースの問題は解決されません。申し訳ありませんが、これは実際の答えではありませんが、同様の状況で作業したため、クライアントはおそらく、より現実的なレポートソリューション、またはエンジニアリングの資金を前向きに扱う他の多くの投資家を必要としています。

この問題が発生したとき、dbスキーマを一定に保ち、タイムスタンプに基づいてエンティティマッピングファクトリを実装しました。最終的に、クライアントは集計フィールドの計算方法に関する要件を(毎週から毎月に)継続的に変更し、完全に満たされることはありませんでした。

9
Nick Larsen

@NickLarsenおよび@PerformanceDBAからの回答に追加するには

フィールド名などの履歴の変更を追跡する必要がある場合は、 緩やかに変化するディメンション のようなものを調べることをお勧めします。 EAVを使用して動的次元モデル(おそらくルックアップリスト)をモデル化しているように見えます。

これを達成する最も簡単な(そしておそらく最も非効率的な)方法は、EAVテーブルに「現在」の日付フィールドを含め、変更が発生するたびに、現在の日付で(既存のレコードを更新するのではなく)新しいレコードを挿入することです。つまり、「現在の」日付を常に含めるか検索するようにクエリを変更するか、何も指定されていない場合は「今」にデフォルトする必要があります。次に、EAVオブジェクトに結合するベースエンティティは、「現在」の日付が行の「最終更新」日付以下であるEAVテーブルから「上位1」をクエリする必要があります。下降。最悪のシナリオ。名前(「属性」テーブルに格納されている)と値の両方が変更された特定の行に対する最新の変更を追跡する必要がある場合、「最終変更」を使用してこのロジックを値テーブルにチェーンします。行の特定の日付に適切な値を見つけるために。

これは明らかに、多くの変更がある場合に大量のデータを生成する可能性があります。このため、このアプローチは「ゆっくりと」変化すると呼ばれています。変更される可能性があるが、それほど頻繁ではない次元値を対象としています。クエリのパフォーマンスを向上させるには、「現在」および「最終更新」フィールドのインデックスが役立つはずです。

0
CodeMonkey