外键 VS 主键上的聚集索引

Posted

技术标签:

【中文标题】外键 VS 主键上的聚集索引【英文标题】:Clustered Index on Foreign Key VS Primary Key 【发布时间】:2017-08-20 03:32:31 【问题描述】:

表结构(SalesPersonProduct)

SalesPersonProductId INT (PK, Clustered)   
SalesPersonId        INT (FK - non-unique - Nullable) 
ProductId            INT (FK - non-unique - Nullable)
AreaId               INT  (Not Null)
DistributionType     INT  (Not Null)
ItemOrder            INT  (Not Null)
ItemSize             INT  (Not Null)

场景:SalesPersonId 是非唯一的,实际上此列中可能有 70 - 80 个重复项。但是,这是唯一用于读取和连接的列,并且当前没有索引。

SalesPersonProductId 仅用作 PK 以供参考,对这些表的更新是通过 PK 处理的,但很少见。将行添加到表后,PK 或 SalesPersonId 都不会更新。

问题: 假设我不能对表结构或相关表进行任何更改。将现有的 PK 更改为非聚集索引并将 SalesPersonId 添加为聚集索引是否会更好?或者只是将 SalesPersonId 添加为标准的非聚集索引?

我知道在幕后,许多非唯一值将获得唯一标识符 - 但是此列几乎用于所有读取,我希望这将提供最佳性能增益,尽管以额外的成本为代价字节现在用于保留这个新聚集索引的“唯一性”。

【问题讨论】:

成本不是额外的字节,而是由于集群键没有每个增加的模式而导致的写入页面拆分。如果有很多写入,您可能会发现非聚集索引(可能将最常见的列包含为非键列)更好。如果您主要阅读并读取足够多的数据,SalesPersonID 上的非聚集索引实际上会导致您出现问题,那么您可能会发现将SalesPersonId 作为您的聚集键可以获得净收益。长话短说,这取决于。做一些测试。 除了SalesPersonProductId 之外,还有什么能让你的行独一无二的吗? (SalesPersonId, ProductId) 是唯一的吗? @AntonínLejsek - 否 @SqlZim - 可能是(SalesPersonId、ProductId、AreaId) 【参考方案1】:

你错过了一件事。

i) 哪个列将最常用于搜索,即在 where 子句中使用最多。如果 SalesPersonId 然后将其设为 CI,或者您可以将 SalesPersonId 和 productid 都设为 CI。

ii)如果您可以更进一步,那么还可以计算索引的选择性

https://www.google.co.in/webhp?sourceid=chrome-instant&rlz=1C1CHMO_enIN556IN556&ion=1&espv=2&ie=UTF-8#q=how+to+find+selectivity+of+an+index

【讨论】:

以上是关于外键 VS 主键上的聚集索引的主要内容,如果未能解决你的问题,请参考以下文章

聚集索引和唯一索引的区别是啥?

如何在 SQL Server 中创建聚集索引,同时仍保留主键?

怎么取消自增列上的聚集索引

mysql中的InnoDB和MyISAM

使用 IN vs = 运算符时在非主键列上使用聚集索引

SQL Server 查询优化器运行方式