3

我发现了很多帖子,这些帖子的开头就像很多时候我遇到过的人说“聚簇索引基于聚簇索引键对表内的数据进行物理排序”。这不是真的!然后这些帖子继续描述它是如何通过链接列表或其他方式实际存储的。例如,这篇文章

每个索引行包含一个键值和一个指向 B 树中的中间级别页面或索引叶级别中的数据行的指针。索引的每个级别中的页面都链接在一个双向链接列表中。数据链中的页面和其中的行按聚集索引键的值排序。

这就引出了我的问题,数据页存储表数据的地方,对吧?那么如果对它们进行排序,并且其中的数据也按照索引列的值进行排序,为什么说聚集索引保持表数据按排序顺序是错误的呢?这是一张来自 Kalen Delaney 书中的图片,它显示了带有 CI 的表中的叶子页面都是根据 CI 值排序的:

在此处输入图像描述

4

5 回答 5

6

你是对的。

聚集索引不会根据聚集索引键对表内的数据进行物理排序。如果是这种情况,那么插入到没有可用空间的大表中间将需要大量的 IO 来为新记录腾出空间。

而是从文件中的任何位置分配一个新页面并链接到链接列表中。

页面的物理顺序与逻辑顺序的不同程度就是逻辑碎片的程度。重建或重组索引可以减少这种情况。

于 2012-08-31T12:45:07.807 回答
2

创建索引时,还会创建一个索引表(我认为它称为索引分配映射(IAM),名称不太清楚)如果是聚集索引,索引表包含索引列,以及指向实际记录。

所以当一个表有聚集索引时,数据可能不会在表上进行物理排序。磁盘中的数据将作为链表维护,聚集索引是指向该数据的指针。

现在索引表将被物理排序......而不是实际的表......并且索引表被维护为 B-Tree,因此搜索会更快。

现在当你创建一个非聚集索引时,它会指向聚集索引表

编辑:(正如 marc_s 指出的那样)聚集索引的叶节点实际上包含数据,而在非聚集索引中则包含指针..

但我还是不相信,它会重新排序磁盘中的数据,它只会重新排序指针

于 2012-08-31T10:49:01.890 回答
0

聚集索引按索引的列对表数据进行排序。插入或更新时,每个新行都将位于表的正确位置。

非聚集索引不会发生这种情况。

于 2012-08-31T10:54:49.643 回答
0

下面的博客文章清楚地解释了聚集索引是如何存储的。

聚集索引是否真的按键顺序物理存储行?

于 2015-08-17T11:13:35.213 回答
-1

我在这里的原始陈述是错误
的 ,因为任何索引都不会影响表中的数据。聚集索引只是指向表中数据的另一种类型的索引。它不会更改顺序或对数据执行任何其他操作。
您始终可以在创建(聚集或非聚集)索引之前和之后直接从具有行号的表中获取数据。
原始声明结束

需要更正(我不经常使用 MSSQL,所以以前从未有机会对此进行测试)
似乎 MSSQL 将聚集索引实现为根本不是真正的索引,但可能更接近触发器/约束对。

从我现在的粗略测试来看:

1)

CREATE TABLE testTable ...  
INSERT ... (few rows)  
SELECT * FROM testTable  

这显示了插入顺序中的所有结果

2)

CREATE CLUSTERED INDEX ... ON testTable (...); 
INSERT ... (few rows)  
SELECT * FROM testTable  

CLUSTERED INDEX
这显示了按3)中的字段排序的所有结果

DROP INDEX (CLUSTERED INDEX Name) ON testTable;
INSERT ... (few rows)  
SELECT * FROM testTable  

这以相同的顺序显示了步骤 2) [之前DROP INDEX]的所有结果,并再次以插入顺序显示了稍后 [在步骤 3)] 中插入的行。

对我来说,这意味着 MSSQL确实重新排序了实际的数据记录(很可能在插入/删除时付出了巨大的代价)。

所以,我站着纠正和指责。老实说,我从没想过会出现这种情况(聚集索引行为,而不是我被证明是错误的)。

于 2012-08-31T10:48:34.863 回答