了解聚集索引
Posted
技术标签:
【中文标题】了解聚集索引【英文标题】:Understanding clustered index 【发布时间】:2016-01-03 08:19:19 【问题描述】:由于PostgreSQL
不支持聚集索引,我正在考虑MSSQL
服务器。我已阅读 article 比较聚集和非聚集索引。这篇文章的要点是(强调我的):
非聚集索引存储一个值和一个指向实际的指针 保存该值的行。
还有
聚集索引不需要存储指向实际行的指针 因为表中的行存储在磁盘上 与聚集索引完全相同的顺序
正如there 和there 告诉我的那样,支持表数据的物理 排序非常困难,特别是如果表被拆分为多个驱动器。现在,我遇到了聚集索引概念,假设数据以某种物理顺序存储。这就是我所困惑的。
问题:什么是聚集索引结构?是否支持tree
类结构遍历,就像PosgtreSQL
对btree
索引所做的那样?
【问题讨论】:
所以你想从 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.叶级
聚集索引包含叶级别的数据行。 如果您在索引列中搜索值,则查询引擎将首先在根级别查找该值,如果该值在根级别可用,则查询引擎将不会进入中间级别或叶级别。如果该值不是基于根级别,那么它将在中间级别或叶级别搜索该值。 如果数据行数太少,则聚集索引中没有可用的中间级别。
下图可以帮助你理解聚集索引的基础知识:
【讨论】:
以上是关于了解聚集索引的主要内容,如果未能解决你的问题,请参考以下文章