避免基于递增键创建聚簇索引

时间:2011-03-14 18:07:58

标签: sql sql-server performance indexing

我从mssqlcity.com得到了这个提示。但是,我无法理解它的解释。

避免基于递增键创建聚簇索引

  

例如,如果一个表有代理   整数主键声明为   IDENTITY和聚集索引是   在此列上创建,然后每个   时间数据插入此表中,   行将添加到结尾   桌子。当有很多行时   可能会出现“热点”。热的   当许多查询尝试时,会出现“现场”   在同一区域读取或写入数据   同一时间。一个“热点”导致   I / O瓶颈。注意。默认情况下,SQL   服务器为。创建聚簇索引   主键约束。所以,在这   case,你应该明确指定   NONCLUSTERED关键字表示   为...创建非聚集索引   主键约束。

在我阅读之前,我想如果我选择一个本质上是随机的列,那就不正确了,因为这会在添加新行时导致不必要的页面重定位。所以,我认为使用排序列是可取的。

在阅读了这个提示之后,我认为它试图说我们并不是真的想要使用直线排序的列作为我们的聚簇索引,因为这些写密集型应用程序会出现I / O瓶颈。

我真的不明白他们所谈论的I / O瓶颈的原因。他们是说共享同一页面的太多操作会减慢磁盘操作的速度吗?这是怎么发生的?有人可以向我解释一下吗?

3 个答案:

答案 0 :(得分:7)

他们所指的热点在SQL Server 2005及更新版本中不是问题。

所发生的事情是,所有数据都被写入聚集索引的同一区域和磁盘上的相同扇区,这导致一次创建大量脏页(脏页是数据)已更改但未提交到磁盘的页面,并且当刷新或检查点运行时,这可能会导致问题。

由于IO架构的变化(根据我的理解),较新版本不会遇到此行为。

答案 1 :(得分:4)

好吧,我之前听过同样的故事。显然这是一个神话。通常建议使用增长的集群主键。所有主要数据库供应商都知道这一点并减轻了您为避免增长密钥而引用的情况。

另见https://dba.stackexchange.com/questions/1584/is-avoid-creating-a-clustered-index-based-on-an-incrementing-key-a-myth-from-sq

引用也违背了建议(来自同一页):

  

考虑创建代理整数主键(例如,标识)。   每个表必须具有主键(数据库表中行的唯一标识符)。代理主键是具有唯一值但对记录本身没有实际意义的字段,因此用户永远不应该看到或更改代理主键。一些开发人员使用代理主键,其他人使用数据字段本身作为主键。如果主键由许多数据字段组成且大小很大,请考虑创建代理整数主键。这可以提高查询的性能。

答案 2 :(得分:4)

所有现代交易数据库(过去十年开发的现代手段)都使用交易记录。

这意味着对数据库的所有更改都以顺序方式写入特殊文件(称为事务日志),然后特殊的专用进程会解析此文件并将更改应用于实际数据。这称为CHECKPOINT

如果十个线程将十条记录插入到具有IDENTITY列的表中,则引擎将创建十个事务日志记录(由一个名为Log Writer的进程一个接一个地写入),然后,是CHECKPOINT的时间,这些记录将被写入适当的数据页面(也可以通过一个名为Checkpoint的过程。)

由于它们是连续的,很可能,它们将在单个I/O操作中写入单个数据页面,并且不会发生页面拆分,因为它们之后没有数据。

如上所述,不断递增的密钥上的聚簇索引比随机密钥的更多更有效。