这种情况的最佳数据库结构是什么?

Ric*_*tts 3 database sql-server database-design entity-framework domain-model

我有一个数据库,持有房地产MLS(多重上市服务)数据.目前,我有一个表,其中包含所有列表属性(价格,地址,平方英尺等).有几种不同的属性类型(住宅,商业,租赁,收入,土地等),每种属性类型共享大多数属性,但有一些属性类型是唯一的.

我的问题是共享属性超过250个字段,这似乎在一个表中有太多字段.我的想法是我可以将它们分解为EAV(实体 - 属性 - 值)格式,但我已经阅读了很多关于它的不好的事情,它会使运行查询变得非常痛苦,因为可以搜索250个字段中的任何一个.如果我要去那条路线,我真的必须从EAV表中提取所有数据,按列表ID分组,将其合并到应用程序端,然后针对内存对象集合运行我的查询.这似乎也不是很有效.

我正在寻找关于以何种方式进行的一些想法或建议.也许250+字段表是唯一的方法.

就像一张纸条,我正在使用SQL Server 2012,.NET 4.5 w/Entity Framework 5,C#,数据通过WCF服务传递给asp.net Web应用程序.

提前致谢.

Dan*_*rod 5

让我们考虑替代品的利弊:

所有列表+属性的一个表格:

  1. 非常宽的表 - 很难查看模型和模式定义和表数据
  2. 一个没有连接的查询需要检索列表中的所有数据
  3. 需要为每个新属性更改架构+模型.
  4. 如果您始终加载所有属性,并且大多数项目具有大多数属性的值,则效率很高.
  5. 示例LINQ查询根据属性:
context.Listings.Where(l => l.PricePerMonthInUsd < 10e3 && l.SquareMeters >= 200)
    .ToList();
Run Code Online (Sandbox Code Playgroud)


一个表用于所有列表,一个表用于属性类型,一个用于(列出ID +属性IDS +)值(EAV):

  1. 列表表很窄
  2. 如果数据非常稀疏(大多数属性没有大多数项的值),则效率很高
  3. 需要从值中获取所有数据 - 一个额外的查询(或者一个会浪费带宽的连接 - 将获取每个属性值行的基本列表数据)
  4. 不需要对新属性进行架构+模型更改
  5. 如果您希望通过代码安全地访问属性,则需要基于属性类型表自定义代码生成
  6. 示例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();
Run Code Online (Sandbox Code Playgroud)

或:(比较实际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();
Run Code Online (Sandbox Code Playgroud)

然后:

var listings = context.Listings.Where(l => listingIds.Contains(l.ListingId)).ToList();
Run Code Online (Sandbox Code Playgroud)


妥协选项 - 所有列表都有一个表,每组属性包含一个表(包括值)(假设您可以将属性划分为组):

  1. 多个中等宽度表
  2. 如果每组数据稀疏,则效率很高(例如,对于没有花园的列表,与花园相关的属性都为空,因此您不会为它们添加与花园相关的表格的行)
  3. 需要一个具有多个连接的查询(带宽不会在连接中浪费,因为组表是1:0..1与列表,而不是1:多)
  4. 需要对新属性进行架构+模型更改
  5. 使查看架构/模型更简单 - 如果您可以将属性划分为10个组,则列表中将有25个表,其中包含11列而不是另外250个列
  6. LINQ查询介于上述两个示例之间.


根据您的具体统计数据(关于稀疏性)和需求/可维护性计划(例如,添加/更改属性类型的频率?)来决定利弊.