聚集索引和非聚集索引的性能问题

9

我有一个包含大约1000万行数据的巨型表格,使用随机唯一标识符作为聚集主键。我在这个表格上进行的最常见的操作是,在没有相同主键的情况下插入新的行。(为了提高性能,我使用IGNORE_DUP_KEY = ON选项)

我的问题是

我能否完全放弃该表格上的聚集索引?我的意思是,当我向带有聚集索引的表格中插入一行时,它应该重新安排物理数据。也许放弃聚集索引并在该列上创建非聚集索引可以避免数据重排?

我不能在实时数据库上进行实验,因为如果性能下降,那将是一个头疼的问题。在测试数据库中,我只能看到有聚集索引的情况下出现“Clustered Index Insert 100%”,而在无聚集索引的情况下出现“table insert”和一些寻找操作。

谢谢您的帮助。


1
一个GUID作为聚集索引并不是一个很好的选择,特别是在大表上 - 参见Kim Tripp: GUID as a primary key。尝试使用INT IDENTITY作为你的聚集键 - 这应该会有很大的改进!但不要完全摆脱你的聚集键 - 一个堆栈甚至更慢... - marc_s
同意marc_s的观点:你会看到很多页面分裂... - Mitch Wheat
你是否进行过任何测量,证明聚集索引导致插入性能问题?如果你只是猜测,我建议你先进行测量,遵循等待和队列方法:http://technet.microsoft.com/en-us/library/cc966413.aspx - Remus Rusanu
1个回答

12

GUID(全局唯一标识符)可能是作为您的主键的自然选择,如果您真的必须使用它作为表的主键,那么您可能会争辩使用它。但我强烈建议不要使用GUID列作为聚集键,因为SQL Server默认情况下会这样做,除非您明确告诉它不要这样做。

您需要分开考虑两个问题:

1)主键是一个逻辑结构 - 候选键之一,可唯一可靠地标识表中的每一行。这可以是任何东西 - INT、GUID、字符串 - 选择对您的场景最有意义的。

2)聚集键(定义表上“聚集索引”的列)- 这是一个与物理存储相关的东西,在此处,小而稳定的、不断增长的数据类型是您的最佳选择 - 默认选项为INTBIGINT

默认情况下,SQL Server表上的主键也用作聚集键 - 但这并非必须如此!我个人见过将以GUID为基础的主/聚集键拆分为两个单独键时获得的大量性能提升 - 主(逻辑)键在GUID上,聚集(排序)键在单独的INT IDENTITY(1,1)列上。

正如索引女王Kimberly Tripp和其他人多次指出的那样 - 将GUID作为聚集键并不是最佳选择,因为由于其随机性,它将导致大量页面和索引碎片以及通常的性能问题。

是的,我知道 - 在SQL Server 2005及以上版本中有newsequentialid() - 但即使如此,它也不是真正的完全顺序的,因此还会遇到与GUID相同的问题 - 只是稍微不那么明显。

考虑另一个问题:在表上的聚集键也会添加到每个非聚集索引的每个条目中,因此您确实希望确保它尽可能小。通常,对于绝大多数表来说,使用具有20亿以上行的INT类型将足够 - 与使用GUID作为聚集键相比,您可以在磁盘和服务器内存中节省数百兆字节的存储空间。

快速计算 - 使用INT与GUID作为主键和聚集键:

  • 具有1'000'000行的基本表(3.8 MB vs. 15.26 MB)
  • 6个非聚集索引(22.89 MB vs. 91.55 MB)

TOTAL: 25 MB vs. 106 MB - 而且这只是单个表的数据!

更多的思考材料 - 由Kimberly Tripp撰写的优秀文章 - 阅读它,阅读它再次消化一下!它真的是SQL Server索引的要义。正如她在"聚集索引辩论继续"一文中所示,拥有良好的聚集键(相对于没有或不良的聚集键)确实可以加速几乎所有数据库操作!这是一个好主意 - 但它必须是一个好的聚集键...

  • 磁盘空间很便宜 - 但这不是重点!
  • Marc


    谢谢马克提供非常明确的解释!我需要一些时间来思考,然后再写出结果。 - irriss
    我们可以将日期时间列用作新的聚集键吗?在该表中有一个“CreatedDate”列,有时我们需要获取max(CreatedDate)。它是顺序的且永不更改。 - irriss
    1
    @Ruslan:你可以这样做,但最好不要独自操作。DateTime不能保证唯一性,如果不唯一,SQL Server将为每个条目添加4个字节...不建议这样做... INT IDENTITY确实是最好的选择-可能与DateTime一起使用(但我不会将DateTime列放入聚集键中)。 - marc_s

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接