ef-core - bool index vs history table

时间:2016-11-08 14:28:26

标签: entity-framework entity-framework-core

我正在使用aspnet-core,ef-core和sql server。我有一个'订单'实体。因为我期望订单表很大,而且最常见的查询只能获得某些客户的活动订单(活动订单只占整个表的一小部分)我喜欢优化查询的速度但是我可以从这两种方法中决定:

1)我不知道这是否可行,因为我之前没有这样做,但我正在考虑创建一个名为'IsActive'的布尔列并使其成为索引,因此在查询时只有Active订单会更快

2)当订单变为未激活时,将订单移至另一个表格,即HistoricalOrders,从而使订单表保持较小。

两者中的哪一个会有更好的结果?或者这些都不是一个好的解决方案,可以建议第三种方法?

2 个答案:

答案 0 :(得分:0)

如果要分割冷数据,那么前导布尔索引列是执行此操作的有效方法。必须将该列添加到要进行热/冷分区的所有索引。这包括聚集索引。这很尴尬。查询优化器要求您添加虚拟谓词where IsActive IN (0, 1),以使其能够仍然在此类索引上进行搜索。当然,现在这也会触及冷数据。因此,您可能需要了解IsActive的具体值或首先尝试1值,并确保它在99%的时间内匹配。

根据架构,这可能是不切实际的。我从未见过这样的好案例,但我确信它存在。

另一种方法是使用分区。在这里,查询优化器无论如何都用于探测多个分区,但你又不想让它探测冷数据。即使它没有找到任何东西,这也会将页面拉入内存,使得分区没有实际意义。

历史表的想法(例如HistoricalOrders)在不同的服装中是相同的。

所以为了完成这项工作,你需要:

  1. 修改您所关注的所有索引(可能全部)或分区,或创建历史记录表。
  2. 有办法几乎不需要探测冷分区。
  3. 我认为(2)在大多数情况下都会杀死它。

    在3种解决方案中,我可能会选择索引解决方案,因为它最简单。如果你担心人们总是通过写错误的查询来犯错误,我会选择一个单独的表格。这会让错误变得很难,但会让代码变得很尴尬。

    请注意,许多索引已经自然分区。标识列或不断增加的日期时间列上的索引最后很热,其他地方很冷。 (OrderStatus INT, CreateDateTime datetime2)上的索引每个订单状态会有一个热点,否则会冷。所以这些已经解决了。

    Some further discussion.

答案 1 :(得分:-2)

在考虑新表HistoricalOrders之前,只需创建一个列名IsActive并使用您的数据对其进行测试。您不需要将其作为索引列.B' cos索引会占用存储空间并且会减慢写入和更新速度。所以我们在创建索引时必须非常小心。当您查询数据时,请执行以下操作。在下面的查询中,数据选择(或过滤器)在SQL srever side(IQueryable)。所以它非常快。

注意:也使用AsNoTracking()。它也会提升性能。

var activeOrders =_context.Set<Orders>().Where(o => o.IsActive == true).AsNoTracking()
.ToList();

参考: AsNoTracking()