代码之家  ›  专栏  ›  技术社区  ›  scherand

SQL Server聚集索引:(物理)数据页顺序

  •  1
  • scherand  · 技术社区  · 16 年前

    我很难理解sql server 2005中的聚集索引是什么。我读了MSDN的文章 Clustered Index Structures (除其他外)但我仍然不确定我是否理解正确。

    (主要)问题是: 如果我将一行(使用“低”键)插入到具有聚集索引的表中,会发生什么情况?

    上述MSDN条款规定:

    数据链中的页及其行按聚集索引键的值排序。

    Using Clustered Indexes 例如声明:

    例如,如果将一条记录添加到接近顺序列表开头的表中,则该记录之后的表中的任何记录都将需要移动以允许插入该记录。

    这是否意味着,如果我将一个非常“低”键的行插入到一个已经包含大量行的表中 所有行都物理移位 在磁盘上?我真不敢相信。这需要很长时间,不是吗?

    或者(正如我猜想的那样)有两种情况取决于第一个数据页的“满”程度。

    • a)如果页面有足够的可用空间容纳记录,则将其放入现有数据页面中,并且数据可能(物理上)重新排序 在那一页里 .
    • b)如果页面没有足够的可用空间用于记录,将创建一个新的数据页面( 磁盘上的任何地方! )与b-树的叶级前端“相连”?

    这意味着数据的“物理顺序”仅限于“页面级别”(即在数据页面内),而不限于驻留在物理硬盘上连续块上的页面。然后,数据页以正确的顺序链接在一起。

    或者以另一种方式表示:如果SQL Server需要读取具有聚集索引的表的前N行,它可以按顺序读取数据页(在链接之后) 但这些页面在磁盘上不一定是按块顺序排列的 (因此磁头必须“随机”移动)。

    我有多近?:)

    2 回复  |  直到 16 年前
        1
  •  3
  •   marc_s MisterSmith    16 年前

    如果你碰巧插入了一行“低”id,那么是的-它将被放置在其他行的附近,这些行已经有了类似的id。

    如果SQL Server页(8K块)已填充到最大值,则 页面分割 将发生-一半的行将保留在该页上,另一半将移动到新页。这两个新页面现在有一些新行的容量。

    这就是为什么您不想使用非常随机的东西作为集群键的原因之一,例如guid,它将导致行被插入到所有地方。

    试图避免页面拆分(这是非常昂贵的操作)是古鲁喜欢 Kimberly Tripp heavily advocate using something that is ever increasing 作为你的聚类键-例如一个int标识列。在这里,新值总是保证大于数据库中已有的任何值,因此新行总是添加在食物链的“末尾”。

    更多优秀的背景信息,请看金伯利·特里普斯的博客-尤其是她的博客 Clustering Key 类别!