代替案の長所と短所を考えてみましょう。
すべてのリストと属性の1つのテーブル:
- 非常に幅の広いテーブル-モデルとスキーマの定義およびテーブルデータを表示するのが難しい
- リストのすべてのデータを取得するために必要な結合のない1つのクエリ
- 新しい属性ごとにスキーマとモデルの変更が必要です。
- 常にすべての属性をロードし、ほとんどのアイテムにほとんどの属性の値がある場合に効率的です。
- 属性に従ったLINQクエリの例:
context.Listings.Where(l => l.PricePerMonthInUsd < 10e3 && l.SquareMeters >= 200)
.ToList();
すべてのリストに1つのテーブル、属性タイプに1つのテーブル、(リストID+属性IDS+)値(EAV)に1つのテーブル:
- リスティングテーブルが狭い
- データが非常にまばらな場合に効率的です(ほとんどの属性にはほとんどのアイテムの値がありません)
- 値からすべてのデータをフェッチする必要があります-1つの追加クエリ(または1つの結合、ただし帯域幅を浪費します-属性値の行ごとに基本的なリストテーブルデータをフェッチします)
- 新しい属性のスキーマとモデルの変更は必要ありません
- コードを介して属性にタイプセーフにアクセスする場合は、属性タイプテーブルに基づいてカスタムコードを生成する必要があります
- 属性に従ったLINQクエリの例:
var listingIds = context.AttributeValues.Where(v =>
v.AttributeTypeId == PricePerMonthInUsdId && v < 10e3)
.Select(v => v.ListingId)
.Intersection(context.AttributeVales.Where(v =>
v.AttributeTypeId == SquareMetersId && v.Value >= 200)
.Select(v => v.ListingId)).ToList();
または:(実際のDBのパフォーマンスを比較してください)
var listingIds = context.AttributeValues.Where(v =>
v.AttributeTypeId == PricePerMonthInUsdId && v < 10e3)
.Select(v => v.ListingId).ToList();
listingIds = context.AttributeVales.Where(v =>
listingIds.Contains(v.LisingId)
&& v.AttributeTypeId == SquareMetersId
&& v.Value >= 200)
.Select(v => v.ListingId).ToList();
その後:
var listings = context.Listings.Where(l => listingIds.Contains(l.ListingId)).ToList();
妥協オプション-すべてのリストに1つのテーブル、値を含む属性のグループごとに1つのテーブル(属性をグループに分割できると仮定):
- 複数の中幅テーブル
- データがグループごとにまばらである場合に効率的です(たとえば、庭のないリストでは庭関連の属性がすべてnullであるため、庭関連のテーブルに行を追加しないでください)
- 複数の結合を含む1つのクエリが必要です(グループテーブルはリストテーブルで1:0..1であり、1:manyではないため、結合で帯域幅が無駄になることはありません)
- 新しい属性にはスキーマとモデルの変更が必要です
- スキーマ/モデルの表示が簡単になります-属性を10のグループに分割できる場合、リストテーブルに別の250の代わりに、11の列を持つ25のテーブルがあります
- LINQクエリは、上記の2つの例の間のどこかにあります。
特定の統計(まばらさに関する)および要件/保守性計画(たとえば、属性タイプが追加/変更される頻度)に従って長所と短所を検討し、決定します。