使用带覆盖列的唯一非聚集索引而不是主键的含义


12

我们有一个大表[MyTable]目前既有Primary Key一个Unique Non Clustered Index在同一列([KeyColumn])。U NC索引还具有其他覆盖列。

在同一列上同时拥有PK和唯一NC索引似乎是多余的,因此我考虑删除主键,而是出于引用完整性的目的而使用唯一非聚集索引。

请注意,该表完全由另一列群集。

即所以我们有:

ALTER TABLE [MyTable]
    ADD CONSTRAINT [PK_MyTable] 
    PRIMARY KEY NONCLUSTERED ([KeyColumn])
GO

CREATE UNIQUE NONCLUSTERED INDEX [IX_MyTable_SomeIndex] 
    ON [MyTable] ([KeyColumn]) 
    INCLUDE ([Column1], [Column2])
GO

据我所知,不可能将覆盖列添加到主键,所以我打算这样做:

  • 放弃依赖于的外键约束 MyTable.KeyColumn
  • 将主键MyTable.KeyColumn完全放在
  • 将外键重新添加到表中(即RI将通过强制执行MyTable.KeyColumn

我能想到的唯一含义是,我们不会在ERD图上看到可视键符号,并且由于包含了列,因此(叶)索引密度会降低。

我已阅读/programming/487314/primary-key-or-unique-index,并对这样做的完整性和性能方面感到满意。

我的问题是:这种方法有缺陷吗?

编辑 我要完成的任务:性能优化和春季大扫除。通过删除PK或索引,我的索引所需的页面将更少=更快的写入速度,再加上维护/操作的好处,即减少索引以保持碎片整理等。

为了提供一些背景知识,我从来没有过没有PK的表被引用过。但是,在表中添加了带有覆盖列的NC索引这一事实意味着我需要调整自己的想法。


您能否评论您要完成的工作?您还应该确保最后得到一个聚集索引。

@ jn29098-更新。确认我们确实在既不是PK也不是Covering列的列上具有聚集索引,因此这似乎与该决定无关。
StuartLC

1
您确定没有任何工具/ ORM /数据生成建模工具会在看到PK消失时发出bar叫声吗?
雷木斯·鲁萨努

我看到的唯一缺点是,一旦PK消失了,那么您在keycolumn上只有一个索引,而使用PK index的查询说对keycolumn进行索引扫描或按keycolumn进行排序,而Uniuqe索引未涵盖这些查询可能会产生一些额外的IO因为唯一的索引叶页面远比PK的页面要多。否则,它看起来还不错。但是一些纯粹主义者会说您应该拥有PK :)
Gulli Meel 2012年

1
我建议您使用索引使用状况DMV检查该索引的有用性,并查看某些查询是否正在使用该索引,并根据唯一键索引对其进行检查,然后使用该索引确定查询将发生什么情况index ..
Gulli Meel

Answers:


3

性能优化。通过删除PK或索引,我的索引所需的页面将更少=更快的写入速度,再加上维护/操作的好处,即减少索引以保持碎片整理等。

您需要能够证明所提出的建议实际上会有所帮助(成本与收益)。出于什么原因考虑此更改?该表实际上存在性能问题,还是只是“看起来错误”?

以下是一些其他问题,可以帮助您针对您的环境做出最佳决策:

  • 在维护窗口中可以节省多少时间?在备份窗口中?

  • 这样可以节省多少存储空间(数据文件,日志文件,备份等)?

  • 现在INSERT这张桌子上的性能真的是瓶颈吗?它会改善多少?删除索引是解决该问题的最佳策略吗?

  • 这是否会导致数据库工具和框架(尤其是ORM)出现问题,这些工具和框架期望每个表都具有主键,而不仅仅是唯一索引?事务复制需要已发布表上的主键。

  • 自我记录数据库模式重要吗?

  • 尽管使用范围有限,但主键索引的狭窄程度是否仍使优化器可以为某些查询生成更有效的计划?(sys.dm_db_index_usage_stats用于查找。)

就您个人而言,根据您的告诉我们,我将不理会它,直到可以证明(a)额外索引是一个问题,并且(b)删除它才是解决方案。


谢谢-事实证明,索引统计数据表明PK仍然大量用于扫描。似乎我太过热心了-从长远来看,保留PK的可读性/常规性优势应胜过任何存储方面的影响。关于事务复制的要点固然重要-我们将需要很快复制该数据库。
StuartLC

2

该表上唯一会变差(并且仅会稍差一点)的查询类型将是请求一定范围的KeyColumn值的查询-因为目前,这些查询最好通过整个PK的索引查找来提供。

值得牢记的是,引用此表的表的参照完整性检查的成本将更高(再次略高)。

只要您注意可为空的方面,那么使用一个索引就可以了。

如果是我的数据库,在其他所有条件相同的情况下,我可能会选择单个唯一索引。


谢谢-您有参考链接吗?更糟糕的是,您是仅指覆盖指数中较低的指数密度,还是有其他原因会导致这种情况?
StuartLC

不幸的是,这只是来自很多经验,并且多年来与比我聪明的人聊天!是的,正是这样-每页行数更少,所以I / O会更多。但是-值得注意的是,INCLUDE列仅存在于叶级别中。因此,这还不是全部。我确定您根据问题的细节知道这一点,但是我想其他读者可能不会知道。
马特·惠特菲尔德

-2

据我所知,不可能将覆盖列添加到主键

如果在KeyColumn上具有聚集索引,则由于它是聚集索引,因此所有其他列都隐式地“覆盖”。因此,通过在KeyColumn上添加另一个索引不会获得任何收益。实际上,您将放慢插入速度并使用更多空间。

这是因为聚集索引不是这样的索引,而只是一条以索引顺序存储表行的指令。一旦您通过主键找到了一行,那么其他所有列都就在那里。


2
从第一段开始:The table is clustered by another column entirely.
JNK

5
我认为这里可能存在一些主键/聚集索引混乱。尽管管理工作室尽了最大的努力说服您,但他们并非同一个人。
马特·惠特菲尔德
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.