我有一个保存房地产 MLS(多重列表服务)数据的数据库。目前,我有一个表包含所有列表属性(价格、地址、平方英尺等)。有几种不同的财产类型(住宅、商业、出租、收入、土地等),每种财产类型共享大部分属性,但也有一些属性是该财产类型所独有的。
我的问题是共享属性超过 250 个字段,这似乎在单个表中包含太多字段。我的想法是我可以将它们分解为 EAV(实体属性值)格式,但我读过很多关于这种格式的不好的东西,这会让运行查询变得非常痛苦,因为可以搜索 250 个字段中的任何一个。如果我要走这条路,我实际上必须从 EAV 表中提取所有数据,按列表 id 分组,在应用程序端合并它,然后针对内存中的对象集合运行查询。这似乎也不是很有效。
我正在寻找一些关于继续进行的想法或建议。也许 250+ 字段表是继续的唯一方法。
请注意,我使用的是 SQL Server 2012、.NET 4.5 w/Entity Framework 5、C#,数据通过 WCF 服务传递到 asp.net Web 应用程序。
提前致谢。
让我们考虑一下替代方案的优缺点:
所有列表+属性的一张表:
- 非常宽的表 - 很难查看模型和模式定义以及表数据
- 无需连接的一次查询即可检索列表中的所有数据
- 需要为每个新属性更改架构+模型。
- 如果您始终加载所有属性并且大多数项目都具有大多数属性的值,则效率很高。
- 根据属性的 LINQ 查询示例:
context.Listings.Where(l => l.PricePerMonthInUsd < 10e3 && l.SquareMeters >= 200)
.ToList();
一张表用于所有列表,一张表用于属性类型,一张表用于(列表 ID + 属性 IDS +)值 (EAV):
- 列表表很窄
- 如果数据非常稀疏(大多数属性没有大多数项目的值),则效率很高
- 需要从值中获取所有数据 - 一个额外的查询(或者一个连接,但是,这会浪费带宽 - 将获取每个属性值行的基本列表数据)
- 不需要为新属性更改架构+模型
- 如果您希望通过代码对属性进行类型安全访问,则需要基于属性类型表生成自定义代码
- 根据属性的 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();
或:(比较实际数据库的性能)
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:0..1,而不是 1:many)
- 需要对新属性进行模式+模型更改
- 使查看模式/模型更简单 - 如果您可以将属性分为 10 个组,您将拥有 25 个包含 11 列的表,而不是列表表上的另外 250 个表
- LINQ 查询介于上述两个示例之间。
根据您的具体统计数据(关于稀疏性)和需求/可维护性计划(例如添加/更改属性类型的频率?)考虑利弊并做出决定。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)