質問

今後リリースされるスーパーヒーロー映画に関するインサイダー情報を収集していて、メインの映画テーブルが次のようになっているとします。

表1

Title              Director   Leading Male      Leading Female    Villain
--------------------------------------------------------------------------
Green Lantern      Kubrick    Robert Redford     Miley Cyrus     Hugh Grant  
The Tick          Mel Gibson  Kevin Sorbo        Linda Hunt    Anthony Hopkins

これは一般に非常にうまく機能し、非常に簡単なクエリや行間の比較が可能になります。

ただし、各データ事実のソースと、その事実を発見したジャーナリストの名前を追跡したいと考えています。これはある種のことを示唆しているようです EAV このような表:

表2

Movie             Attribute            Value          Source          Journalist
----------------------------------------------------------------------------------
Green Lantern      Director           Kubrick         CHUD              Sarah
Green Lantern    Leading Male      Robert Redford     CHUD              James
Green Lantern   Leading Female      Miley Cyrus    Dark Horizons        James
Green Lantern      Villain           Hugh Grant       CHUD              Sarah
The Tick           Director          Mel Gibson       Yahoo            Cameron
...

これにより、必要なメタデータを簡単に取得できる一方で、クエリが難しくなります。1 つの映画のすべての基本データを単純に取得するには、もう少し時間がかかります。具体的には、グリーン ランタンに関する 4 つの重要な情報を取得するには、ここでは 4 行を処理する必要がありますが、表 1 では、それは 1 つの適切にカプセル化された行です。

そこで私の質問は、今説明した複雑さを考慮すると、一般的に EAV テーブルは避けるべきであることはわかっているのですが、それでも EAV が最良の解決策なのでしょうか?それがこのデータを表現する唯一の合理的な方法であるように思えます。私が考える他の唯一の代替案は、テーブル 1 を別のテーブルと組み合わせて使用​​することです。 のみ 次のようなメタデータを格納します。

表3

Movie             Attribute            Source          Journalist
----------------------------------------------------------------------------------
Green Lantern      Director             CHUD              Sarah
Green Lantern    Leading Male           CHUD              James
Green Lantern   Leading Female      Dark Horizons         James
Green Lantern      Villain              CHUD              Sarah
The Tick           Director             Yahoo            Cameron
...

しかし、これは非常に危険です。誰かが表 1 の列名を「悪役」から「主悪役」などに変更しても、表 3 の行には単に「悪役」が表示されたままになり、残念ながら関連データが切り離されてしまうからです。これは、「属性」列がテーブル 1 の列の列挙として機能する別のテーブルにリンクされている場合に役立ちます。もちろん、DBA はこの列挙テーブルをテーブル 1 の実際の列と一致するように維持する責任があります。そして実際には、列挙テーブルを手動で作成する代わりに、テーブル 1 の列の名前を格納する SQL Server のシステム ビューを使用することで、これをさらに改善できる可能性があります。ただし、システム ビューを含む関係を構築できるかどうかはわかりません。

何を指示してるんですか?EAV が唯一の方法でしょうか?

そして、それが 1 つのメタデータ列だけ (「ジャーナリスト」なしの「ソース」のみ) だった場合はどうなるでしょうか。それでも EAV ルートを選択する必要があるのでしょうか?「Director」、「Director_Source」、「Leading Male」、「Leading Male_Source」などの列を含めることもできますが、これはすぐに見苦しくなります。私が考えていないより良い解決策はありますか?

明確にしていない点がある場合は、コメントしてください。必要に応じて追加します。そうそう、私が使用した映画データは捏造されたものです :)

編集:私の主な質問を簡潔に言い直すと、安全でアクセス可能な方法で属性のメタ データを保存しながら、映画のエントリを実際によく表している表 1 のシンプルさと真の RDBMS 設計を実現したいと考えています。これは可能でしょうか?それともEAVが唯一の方法でしょうか?

編集2:さらに Web 調査を行った結果、列にメタデータを保存するという要望を中心とした EAV に関する議論をまだ見つけていません。EAV を実装する主な理由は、ほとんどの場合、動的で予測不可能な列ですが、この例には当てはまりません。私の例では、常に同じ 4 つの列があります。監督、主演男性、主演女性、悪役。ただし、各行の各列に関する特定の事実 (情報源とジャーナリスト) を保存したいと考えています。EAV を使用するとこれが容易になりますが、それに頼ることは避けたいと考えています。

アップデート

列の名前を「Movie」から「Name」に変更し、テーブル全体を「Movie」と呼ぶことを除いて、テーブル 2 の設計を使用して、テーブル 1 を取得するための SQL Server 2008 でのピボット操作を次に示します。

SELECT Name, [Director], [Leading Male], [Leading Female], [Villain]
FROM (Select Name, Attribute, Value FROM Movie) as src
PIVOT
(
Max(Value)
FOR Attribute IN ([Director], [Leading Male], [Leading Female], [Villain])
)  AS PivotTable
役に立ちましたか?

解決

設計内でファクト値とみなすものを変更できます ...データ モデル内のファクトは次の N タプルとして表現できるようです。

Movie | FactType | FactValue | FactSource | FactJournalist

次のテーブル構造は必要なデータ モデルをサポートしている必要があり、比較的簡単にインデックス付けと結合を行うことができます。ファクト値とファクト タイプのみをピボットアウトするビューを作成して、次のパースペクティブを作成することもできます。

MovieID | Movie Name | Director | LeadingMale | LeadingFemale | PrimaryVillain | etc

興味深いことに、これは、EAV モデルをデータに完全に適用し、個々の映画 (監督、主演、悪役などの直感的な属性を含む) を、属性がソースに焦点を当てたピボット構造に分解することの論理的拡張であると考えることができます。代わりに情報の。

提案されたデータ モデルの利点は次のとおりです。

  • 十分に正規化されています (ただし、完全を期すために、FactType フィールドを参照テーブルに正規化する必要があるかもしれません)
  • ファクト タイプを効率的にピボットして表構造にするビューを作成することが可能です。
  • 比較的拡張性が高く、データベースで参照整合性と (必要に応じて) カーディナリティ制約を強制できるようになります。
  • MovieFact テーブルをサブクラス化して、単純なテキスト フィールドだけでなく、さまざまな種類の映画ファクトをサポートできます。
  • データに対する単純なクエリは比較的効率的です

データ モデルの欠点には次のようなものがあります。

  • 複合的な条件付きクエリは書くのが難しくなります (不可能ではありません) (例:監督が A、主演男性が B であるすべての映画を検索します...)
  • このモデルは、より伝統的なアプローチや EAV 構造を含むアプローチに比べていくらか明白ではありません。
  • 複数のファクトを更新するには、複数の列ではなく複数の行を更新する必要があるため、挿入と更新は少し難しくなります。

構造を正規化するためにムービー データを 1 つ上のレベルに持っています。また、一貫性を保つためにムービー名を MovieFact 構造にプッシュダウンすることもできます (映画によっては、名前がソース情報を追跡する必要がある可能性があると想像できるため)。 。

Table Movie
========================
MovieID   NUMBER, PrimaryKey
MovieName VARCHAR

Table MovieFact
========================
MovieID          NUMBER,  PrimaryKeyCol1
FactType         VARCHAR, PrimaryKeyCol2
FactValue        VARCHAR
FactSource       VARCHAR
FactJournalist   VARCHAR

架空の映画データは次のようになります。

Movie Table
====================================================================================
MovieID  MovieName
====================================================================================
1        Green Lantern
2        The Tick

MovieFact Table
====================================================================================
MovieID  FactType       FactValue         FactSource       FactJournalist
====================================================================================
1        Director       Kubrick           CHUD             Sarah
1        Leading Male   Robert Redford    CHUD             James
1        Leading Female Miley Cyrus       Dark Horizons    James
1        Villain        Hugh Grant        CHUD             Sarah
2        Director       Mel Gibson        Yahoo            Cameron
2        Leading Male   John Lambert      Yahoo            Erica
...

他のヒント

興味深いシナリオ。エンティティをファーストクラスのオブジェクトとして考えることで、EAV のゲットー性を回避できます。それらを事実と呼びましょう。そして、この場合、すべての映画がまったく同じ 4 つの事実を持っているという点で、かなり直交していることが役立ちます。EAV テーブルを元の/正しいテーブルにすることができ、そのテーブルをマイニングしてデータを適切に正規化された形式 (つまり、最初のテーブル)。これにより、必要なデータとそのメタデータが得られ、マイニング プロセスの実行頻度に合わせて正確な映画情報を簡単にクエリできるようになります。

通常のテーブルと EAV テーブル間で整合性を維持するデータベース内での方法が存在しないように見えるため、データが有効であることを確認するには「データベース外」の技術が確実に必要だと思います。一連の複雑なトリガーを使用すれば、ほとんど何でも達成できると思いますが、問題を「理解」する 1 人の人間の管理者の方が、おそらくはるかに対処しやすいでしょう。

ここに別のアイデアがあります...自由に穴を開けてください:)

Table: Movie
Columns: MovieId|Movie|Director|LeadMale|LeadFemale|Villain

Table: MovieSource
Columns: MovieSourceId|MovieId|MovieRoleId|Source|Journalist

Table: MovieRole
Columns: MovieRoleId|MovieRole
Values: 1|Director, 2|LeadMale, 3|LeadFemale, 4|Villain

私が考えているのは、映画テーブルの列 できた さまざまなタイプにすることができます(あなたの例では、それらはすべて文字列/varcharですが、たとえば、ソースを持つ数値または日付情報である可能性があります)。

ただし、ソース データの列タイプは、おそらく映画データの列タイプの関数として変化しないため、データの整合性を失うことなく、ソースに対して EAV システムをさらに使用できます。

MovieRole テーブルを使用すると、ロールを明示的に列挙できるため、ソースとムービー テーブルの特定のセルの間に確実なリンクを作成できます。

-ダン

ソース データには 2 つのフィールド (Source と Journalist) しかないので、次のようなメタデータ テーブルをお勧めします。

Movie    DirectorSource  DirectorJournalist  LeadingMaleSource  LeadingMaleJournalist ...
---------------------------------------------------------------------------------------
The Tick   Yahoo           Cameron           ...                ...

これにより、重要度の低いソース データがメイン テーブルから除外されますが、クエリは複雑にならず、コードが読みやすくなります。

私はアドバイスするだけです EAV もし ...

  • ソース メタデータのフィールドが 3 つ以上あります
  • あなた 必要 ムービーフィールドを簡単に追加または変更できるようになります。(「悪役」から「正悪役」への変更は1日に数回行われます)

私の返答はSOにとって少し哲学的すぎるように思えるかもしれません。我慢してください。

「出典」列は主題データではなく、むしろメタデータだと思います。それは実際には、私たちが他のデータをどのようにして知るようになるかに関するデータです。それはデータに関するデータ、つまりメタデータになります。

EAV が問題を引き起こす理由の 1 つは、単一行内にデータとメタデータが混在しているという事実です。達成したい結果への中間ステップとして、私自身が意図的にそうすることがあります。しかし、私は成果物の中でデータとメタデータを決して混在させないように努めてきました。

なぜそうしなかったのかはわかりますが、簡潔に説明できません。

誰もこの問題に真剣に取り組んでいないので、私自身の質問に答えようと思います。私は、EAV のようなテーブルが唯一の方法であると確信しています。各列にメタデータ (この場合は情報源とジャーナリストに関する) を保存するには、実際には各列をそれ自体のエンティティとして扱うことになり、これが EAV で許可されます。

あなた できた データを保存するために元の列ごとに 2 番目と 3 番目の列を追加するなど、別の方法を選択することもできますが、それは明らかにいくつかの基本的な正規化ルールに違反しており、おそらく後で苦労するだけです。

ふーむ....私はこれを使用したことがないので、経験に基づいて話しているわけではありません(つまり、うまくいかなくても私を責めないでください)、しかし表面的には、通常のテーブルと同様に常に存在することがわかっている「共通」データと、次のように変化する可能性のある「メタデータ」を保存できるように見えます。 XML。問題は、それを適切にクエリする方法です。説明どおりに実行できると思います。 ここ.

考慮すべきもう 1 つのアプローチは、クラス テーブルの継承です。Bill Karwin が EAV オプションについて素晴らしいレビューを書いています。 このSOの答え, 、そして良い文脈がたくさんあります。

何をコード化する必要があるかに基づいて決定します。

src/journo が単なる追加情報である場合は、さらに列を検討します。しかし、最終的に複雑な src/journo クエリを作成することになることがわかっている場合は、EAV を使用します。メタ テーブルの下でジャーナリストの参照を検索する方が、検索するよりも簡単だからです。 有力女性ジャーナリスト そして 悪役ジャーナリスト

個人的には、src/journo メタデータを EAV スタイルの別のテーブルにダンプしたいと考えていますが、FK を使用して属性定義テーブルを定義します。自由形式の属性テキスト フィールドを持つことは惨事の元です。常に制約を通じて属性を制御してください。必要に応じて、参照整合性を向上させるためにトリガーを実装できます。

私にとって、それは結局のところ視点の問題です。情報源やジャーナリストはそれ自体が関係上の懸念事項であると思いますか、それともそれらは情報を補完する追加のデータにすぎないのでしょうか? 映画?次のレベルの改良は、さまざまなテーブルを作成することです。 ムービーデータソース そして 映画データジャーナリスト これにより、有効なデータを定義するテーブルに FK をマップできるようになります。 情報源 そして ジャーナリスト (そして、それらの情報源/ジャーナリストに関するさらなる情報が具体化される可能性があります)。ここで行うことは、 映画 エンティティと ソース (そしてまた ジャーナリスト) 実在物。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top