聚集索引选择-PK还是FK?


11

我有一个SQL Server 2014表,如下所示:

OrderId     int           not null IDENTITY --this is the primary key column
OrderDate   datetime2     not null
CustomerId  int           not null
Description nvarchar(255) null

我团队中的某些人建议应将聚集索引设置为on OrderId,但由于以下原因,我认为CustomerId+ OrderId是更好的选择:

  • 几乎所有查询都会查找WHERE CustomerId = @param,而不是OrderId
  • CustomerIdCustomer表的外键,因此具有聚集索引CustomerId可以加快连接速度
  • 虽然CustomerId不是唯一的,但OrderId在索引中指定其他列将确保唯一性(我们可以UNIQUE在这两列上创建聚集索引时使用关键字,以避免不唯一性的开销)
  • 插入数据后,CustomerIdOrderId永远不会更改,因此在初始写入后这些行将不会移动。
  • 数据访问通过默认情况下请求所有列的ORM进行,因此当基于的查询CustomerId进入时,聚集索引将能够提供所有列而无需任何其他工作。

是否CustomerIdOrderId做法的声音是最好的选择给出了上述?或者,OrderId由于它是一个单独保证其唯一性的列,它本身会更好吗?

当前,该表在上有一个聚集索引,在上有一个OrderId非聚集索引CustomerId,但是没有覆盖,因此,由于我们使用的是ORM,并且要求所有列,因此检索它们是额外的工作。因此,通过这篇文章,我试图考虑使用更好的CI来提高性能。

我们数据库上的活动是大约85%的读取和15%的写入。

Answers:


5

社区Wiki答案

我认为以CustomerID作为第一列的复合聚集索引键将是最好的,因为这WHERE几乎是所有查询的子句。

与增量键相比,拆分可能会更多(如果您管理和维护填充因子以避免“不良”拆分,则一段时间内页面密度可能会低于最佳)。但是,由于避免了关键字查找,因此客户查询的总体性能提高是可观的。

OrderIDOrderDate可能最适合第二列,具体取决于您最关键的查询。

例如,如果客户在登录网站后看到了最近订单的时间顺序列表,那么应该紧跟OrderDate进行优化ORDER BY OrderDate DESC

如果您选择OrderID作为聚簇索引,并且CustomerID上具有非聚簇索引,那么您仍然会在非聚簇索引中得到拆分和碎片。


3

如果此表是大量写密集型的(例如INSERT,发生了更多的语句,而不是SELECT针对它的语句),那么我将不同意Wiki的答案

选择CustomerID作为复合集群键的第一列将产生很多中间页拆分。希望您有很多现有客户,并且一直都有很多新客户。由于随着业务的持续发展,客户(希望)下达了多个订单,因此这种方法将显示大量的中间页拆分,这不仅会破坏写入性能,还会破坏读取性能,因为索引会严重分散并可能包含更多的空白空间(这意味着浪费了存储和内存)。

如果您认为CustomerID应该是复合聚集索引的前导列,则可以通过FILLFACTOR对该表的所有索引进行调整来减少中间页拆分的影响。通过增加表/索引的大小,这将减少中间页面拆分的数量。如果您想走这条路,我建议您使用80的值进行测试,并减少分析是否显示中间页拆分仍在影响性能的建议。

我的建议是使用OrderId。OrderID自然应该是顺序的,并且会生成更多且预期随着表增长而出现的结束页拆分。此外,如果您选择使用OrderDate列作为分区键,则此方法在表分区中将更好地发挥作用。对于经常使用CustomerID字段的查询,请创建一个非聚集索引来处理这些查询。该索引需要定义适当,FILLFACTOR因为它会遭受上面我提到的中间页拆分的影响,尽管与针对聚集索引的拆分相比,这些总体上不会那么糟糕。

我们数据库上的活动是大约85%的读取和15%的写入。

CustomerIDOrderID如果该评估成立,则+ (并指定填充因子以允许增长而不拆分)可能会更好。只要确保评估是正确的即可。测试测试测试。


1
请注意,在页面上为最后一个(或唯一)客户插入订单不是“中间页面拆分”。因此,如果每位客户的订单数很高,或者行宽很大,则更少的订单插入将需要“中间页面拆分”。
David Browne-微软
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.