3

我有一个保存房地产 MLS(多重上市服务)数据的数据库。目前,我有一个包含所有列表属性(价格、地址、平方英尺等)的表。有几种不同的房产类型(住宅、商业、出租、收入、土地等),每种房产类型共享大部分属性,但也有一些是该房产类型独有的。

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

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

请注意,我使用的是 SQL Server 2012、.NET 4.5 w/Entity Framework 5、C#,并且数据通过 WCF 服务传递给 asp.net Web 应用程序。

提前致谢。

4

3 回答 3

5

让我们考虑一下替代方案的优缺点:

所有列表 + 属性的一张表:

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


一张表用于所有列表,一张表用于属性类型,一张表用于(列表 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();

或:(比较实际数据库的性能)

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


根据您的具体统计数据(关于稀疏性)和需求/可维护性计划(例如属性类型添加/更改的频率?)考虑优缺点并做出决定。

于 2012-12-02T20:38:15.283 回答
0

我可能会做什么:

我首先为 250 个字段创建一个表,其中有 ID 和 FieldName,例如:

price   -> 1
address -> 2
sqft    -> 3

该表还将在我的代码中硬编码为枚举并用于查询。

然后在主表中我有两个字段,一个是从上表中获取的字段ID的类型,第二个是它的值,例如

Line1: 122(map id), 1 (for price), 100 (the actually price)
Line2: 122(map id), 2 (for address), "where is it" 
Line3: 122(map id), 3 (for sqft), 10 (sqft)

这里的问题是您可能至少需要两个字段,一个用于数字,一个用于字符串。

这当然只是一个提议。

于 2012-12-02T20:17:34.560 回答
0

我会创建一个listing只包含共享属性的表。该表将listingId作为主键。它会有一个存储列表类型的列,以便您知道它是住宅列表、登陆列表等。

然后,为每个子类型创建一个额外的表。所以你会有 , 等表residential_listingland_listing所有这些表的主键也是listingId. 此列也是 的外键listing

当您希望对共享数据进行操作时,您可以完全从listing表中执行此操作。当您对特定数据感兴趣时,您将加入特定表。如果所有数据都在那里,某些查询可能能够完全在特定表上运行。

于 2012-12-03T05:01:11.523 回答