聚集索引在哪里存储中间级别的键的行数据?

时间:2017-02-22 09:23:51

标签: sql-server rdbms

请帮助我理解我认为两个事实之间存在不一致的地方:

  1. SQL Server以B树结构存储数据
  2. 只有叶节点包含实际的表数据,而中间节点只存储键和指向子节点的指针
  3. 通常,对于中间节点中的给定键,B树具有以下属性:左子树中的所有键都小于它,而右子树中的所有键都大于此,这样:

    Example B-Tree

    在上面的示例(image credit)中,显然将一个ID = 7的行插入到表中。但是,如果该ID的行数据(非键列)不在示例的根节点中且叶节点中没有7,那么它在哪里?

    显然,除了“索引是B树”之外,还有更多内容,我希望能有所了解。

4 个答案:

答案 0 :(得分:3)

我认为这篇文章的概述很好:

https://www.simple-talk.com/sql/database-administration/sql-server-storage-internals-101/

参见部分索引。示出了作为7或16的节点也具有它们的叶子 另外,我强烈推荐书:

Kalen Delaney的SQL Server 2012 Internals

https://www.amazon.com/Microsoft-Server-Internals-Developer-Reference/dp/0735658560

答案 1 :(得分:2)

构建B-Tree索引时,它从叶级开始 - 数据被排序并写入数据页并创建双链表。

从每个页面获取最小的键值(来自第一页的NULL)并用于构建下一级索引的索引页面,因此索引页面中的每一行都包含下面页面的ID和来自它的最小键值。它再次执行相同的操作,从每个索引页面获取最小的键值,以创建下一个级别。

这一直持续到一切都适合单个页面 - 这是根。

所有中间级别的页面和根目录遵循相同的模式,页面ID和该页面中的最小键值。

在上图中,假设它只是三个叶级页面和根,则根应包含select(pageID:1 Key:NULL)(pageID:2 Key:9)

答案 2 :(得分:2)

该图表用于B树,但从技术上讲,SQL Server使用B +树结构。向下滚动Wiki article,你会发现

  

在B +树中,密钥的副本存储在内部节点中;密钥和记录存储在树叶中;此外,叶节点可以包括指向下一个叶节点的指针,以加快顺序访问(Comer 1979,p.129)。

因此,内部节点只有密钥的副本,并且将在叶子中复制(在聚集索引的情况下,实际数据也被保留)。

您可以找到更多细节here。你会在评论部分注意到其他几个人注意到SQL Server使用的是B +树。

答案 3 :(得分:1)

(请原谅我的Word绘图技巧)

尽管您的图像确实代表了B-Tree,但实际的SQL Server实现略有不同,特别是B + Tree。我也尝试使用视觉效果进行解释,以下图为例:

enter image description here

如图所示,密钥不仅存在于一个节点(在本例中为根),而是复制并分发到子节点直到叶节点。 (在这种情况下,树只有2个级别,根级别和叶级别。)

因此,当运行密钥(Adams, Joe)的查询时,将根据您在问题中提到的规则在B树中查找密钥(左侧较小的键,右侧较大的键) )。

这将持续到达 LEAF 节点。

此时有两个区别,特别是对于SQL Server:

  • 非聚集索引(如上图所示):

    • 包含一个ROW_ID / PAGE_ID列,指向存在该行的数据页
    • 数据库引擎检索该页面并在其中查找ROW_ID
  • 聚集索引:

    • 包含叶级别的整个数据页
    • 数据库不需要检索页面,因为它已经在叶级别,只是查找页面内的键