はじめに
私はEAVデータベースについて読んでいますが、短所のほとんどは、本当に、本当に、悪いEAV設計またはデータからレポートを生成するのが難しいことに関連しているようです.
通常、人々が EAV について不平を言っているのを見るとき、彼らは RDBMS の個別のテーブル + 列の機能を複製しようとして 3 つ未満のテーブルを使用しています。場合によっては、10 進数から文字列まですべてを 1 つのTEXT
値列に格納することを意味します。EAV はまた、注意しないと非常に悪いデータの整合性に対するセーフ ガードを台無しにします。
ただし、EAV は履歴データを追跡する簡単な方法を提供し、システムの一部を SQL とキー バリュー ストア システムの間で行き来させることができます。
タイプに基づいて異なるエンティティ属性を分離するとどうなるでしょうか。これにより、特定の属性とエンティティに関連付けられた適切にインデックス化された値に加えて、begsTo、Has、HasMany、および HasManyThrough 関係を引き続き処理できます。
次の 2 つの基本エンティティを考慮する
products (price -> decimal, title -> string, desc -> text, etc...)
attributes
options
[...]
int
datetime
string
text
decimal
relation
[id,foreign_key]
users (gender -> options, age -> int, username -> string, etc...)
attributes
options
[...]
int
datetime
string
text
decimal
relation
[id,foreign_key]
RDBMS スキーマ設計
ご存知のように、ユーザー プロファイルと製品は、世界で最も多様なアイテムの一部です。各企業はそれらを異なる方法で処理し、ニーズに合わせて異なる「列」または「属性」を持っています。
以下は、複数の (ネストされたおよび/またはリレーショナルな) エンティティを処理する方法のビューです。
アイデアは、エンティティごとにこのマスター属性テーブルがあり、それらの値を見つけて解釈する方法を指定するというものです。これにより、他のエンティティへの外部キーや、「オプション」や 10 進数などの特殊なケースを処理できます。
entity_type { id, type, // つまり、「ブログ」、「ユーザー」、「製品」など.. created_at }
entity {
id,
entity_type_id,
created_at
}
attr {
id,
entity_id,
type,
name,
created_at
}
option {
id,
attr_id,
entity_id,
multiple, // multiple values allowed?
name,
created_at
}
attr_option {
id
attr_id,
entity_id,
option_id
option,
created_at
}
attr_int {
attr_id,
entity_id,
int,
created_at
}
attr_relation {
attr_id,
entity_id,
entity_fk_id,
created_at
}
attr_datetime {
attr_id,
entity_id,
datetime,
created_at
}
attr_string {
attr_id,
entity_id,
var_char,
created_at
}
attr_text {
attr_id,
entity_id,
text,
created_at
}
attr_decimal {
attr_id,
entity_id,
decimal,
created_at
}
このようなテーブルを使用すると、値を変更する新しい属性ごとに を追加して、最新の値が何であるかを知ることがUPDATE ...
できるため、その必要がなくなります。これは、履歴データの記録を保持するのに最適です (もちろん例外はあります)。INSERT INTO ...
created_at
サンプルクエリ
まず、エンティティの「タイプ」は何ですか?(ユーザー、投稿、コメントなど)
SELECT * FROM entity_type et LEFT JOIN entity e ON e.entity_type_id = et.id WHERE e.id = ?
次に、このエンティティの属性は何ですか? (テーブル属性)
SELECT * FROM attr WHERE entity_id = ?
次に、このエンティティの属性にはどのような値が存在しますか? (attr_### テーブル)
SELECT * FROM attr_option, attr_int, attr_relation, attr_text, ... WHERE entity_id = ?
vs
SELECT * FROM attr_option WHERE entity_id = ? if( ! multiple) ORDER BY created_at DESC LIMIT 1
SELECT * FROM attr_int WHERE entity_id = ? ORDER BY created_at DESC LIMIT 1
SELECT * FROM attr_relation WHERE entity_id = ? ORDER BY created_at DESC LIMIT 1
SELECT * FROM attr_text WHERE entity_id = ? ORDER BY created_at DESC LIMIT 1
...
このエンティティにはどのような関係が存在しますか?
ID が 34 の「投稿」エンティティがあり、その「コメント」が必要であると仮定すると (entity_type = 2)、これにより、製品エンティティのコメント エンティティ ID を取得できます。
SELECT * FROM entity AS e
LEFT JOIN attr_relation AS ar ON ar.entity_id = e.id
WHERE ar.entity_id = 34 AND e.entity_type = 2;
複数のクエリ (いずれにしてもキー値ストアで必要) は別として、このアプローチにはどのような問題が存在するでしょうか?