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

And*_*ndy 11 sql-server clustered-index

我有一个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
Run Code Online (Sandbox Code Playgroud)

我团队中的一些人建议聚集索引应该在OrderId,但我认为CustomerId+OrderId将是更好的选择,原因如下:

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

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

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

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

小智 5

社区维基答案

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

与增量键相比,可能会有更多的拆分(或者,如果您管理和维护填充因子以避免“坏”拆分,那么一段时间内可能会出现次优页面密度)。但是,客户查询的整体性能改进是显着的,因为避免了键查找。

根据您最关键的查询,OrderIDOrderDate可能最适合第二列。

例如,如果客户在登录网站后看到按时间顺序排列的最近订单列表,则OrderDate应该是下一个,以优化ORDER BY OrderDate DESC.

如果您选择OrderID作为聚集索引,在CustomerID上使用非聚集索引,您仍然会得到拆分和碎片,只是在非聚集索引中。