了解聚集索引

Posted

技术标签:

【中文标题】了解聚集索引【英文标题】:Understanding clustered index 【发布时间】:2016-01-03 08:19:19 【问题描述】:

由于PostgreSQL 不支持聚集索引,我正在考虑MSSQL 服务器。我已阅读 article 比较聚集和非聚集索引。这篇文章的要点是(强调我的):

非聚集索引存储一个值和一个指向实际的指针 保存该值的行。

还有

聚集索引不需要存储指向实际行的指针 因为表中的行存储在磁盘上 与聚集索引完全相同的顺序

正如there 和there 告诉我的那样,支持表数据的物理 排序非常困难,特别是如果表被拆分为多个驱动器。现在,我遇到了聚集索引概念,假设数据以某种物理顺序存储。这就是我所困惑的。

问题:什么是聚集索引结构?是否支持tree 类结构遍历,就像PosgtreSQLbtree 索引所做的那样?

【问题讨论】:

所以你想从 PostgreSQL 迁移到 MS SQL Server 只是为了获得聚集索引?!? @jarlh 不完全是,我只是想通过MSSQL 示例来理解这个概念。特别是,如果聚簇索引仅以物理方式(以某种方式)对数据进行排序,那就很清楚了。但是我怎么能将它与 btree 结构和物理顺序联系起来。我无法想象它实现的任何方式...... 是什么让你绊倒了?数据可以排序,或者行的数据可以是索引的一部分? @RowlandShaw 啊,看来我明白了。在非聚集索引中,我们需要遍历 btree,以获取指向一行的 指针,并通过该指针获取该行。它会导致驱动头移动以首先获取指针,然后再移动以获取实际行。此外,该表是逐页物理存储的,这进一步减少了头部移动开销。这是对这个概念的正确理解吗? 如果假设您要使用 GUID 作为聚集索引,您的数据将类似于 ('F0CD53B7-5842-49B4-A685-1CEFF8EE750F', 'A3DB7FD6-19B8-4278-AEFE-949DBCD1C9A4'),并且由于聚集索引的性质,数据已排序。由于数据移动和移动以适应新条目,所有随后对该表的插入都将导致数据重组。而使用日期时间......所有新插入只会附加到末尾,不需要重新组织。当您为 CL 索引选择正确的数据类型时,这会大大降低插入成本。 【参考方案1】:

在 SQL Server 中,索引被组织为 B 树。索引 B 树中的每一页称为索引节点。 B树的顶端节点称为根节点。索引中最底层的节点称为叶节点。根节点和叶节点之间的任何索引级别统称为中间级别。在聚集索引中,叶节点包含基础表的数据页。根和中间级节点包含保存索引行的索引页。每个索引行包含一个键值和一个指向 B 树中的中间级别页面或索引叶级别中的数据行的指针。索引的每一级中的页面都链接在一个双向链表中。

聚集索引在 sys.partitions 中有一行,索引使用的每个分区的 index_id = 1。默认情况下,聚集索引只有一个分区。当聚集索引有多个分区时,每个分区都有一个 B 树结构,其中包含该特定分区的数据。例如,如果一个聚集索引有四个分区,那么就有四个 B-tree 结构;每个分区一个。

供参考

https://technet.microsoft.com/en-us/library/ms177443(v=sql.105).aspx http://www.sqlservercentral.com/blogs/practicalsqldba/2013/03/14/sql-server-part-4-explaining-the-non-clustered-index-structure-/

【讨论】:

所以,除了按物理顺序排列的表之外,我们还有实际遍历到物理行的索引行(根级和中间级),对吧? 那么你是说只有一个分区的聚集索引没有B-Tree?【参考方案2】:

在聚集索引中有三个层次

1.根级别

2.中级

3.叶级

聚集索引包含叶级别的数据行。 如果您在索引列中搜索值,则查询引擎将首先在根级别查找该值,如果该值在根级别可用,则查询引擎将不会进入中间级别或叶级别。如果该值不是基于根级别,那么它将在中间级别或叶级别搜索该值。 如果数据行数太少,则聚集索引中没有可用的中间级别。

下图可以帮助你理解聚集索引的基础知识:

【讨论】:

以上是关于了解聚集索引的主要内容,如果未能解决你的问题,请参考以下文章

数据库存储结构:页聚集索引非聚集索引

聚集和非聚集索引 - SQL Server 和 Oracle?

聚集索引和非聚集索引实际上是啥意思?

360什么叫做覆盖索引?

如何将非聚集索引变成覆盖索引

ES 聚合索引简介