哪里保存了B +树的聚簇和非聚簇索引?

时间:2015-12-11 03:14:58

标签: mysql sql indexing b-tree clustered-index

目前我正在阅读有关B+ Tree基础知识的内容,并对群集和非群集索引的空间分配感到困惑。

当我们在B+ tree上创建聚簇索引时,索引会存储在主内存中,而叶子包含指向实际块的数据指针。块存储在磁盘中,块包含记录。

  • 通常在主键
  • 上创建聚簇索引
  • 只能有一个聚集索引

现在假设我们有一个表( id ,名称,类),我在nameclass上创建了两个非聚簇索引。 我怀疑非聚集索引将存储在哪里?以及如何为query之类的

执行搜索
select id, name, class from table where id = 3, name='Leo' and class='10'

enter image description here

我的假设:

  • 由于 id 字段是主键,因此首先使用聚集索引将id = 3
  • 现在使用nameclass上的非聚集索引,我们会找到其余字段

你认为我的假设是对的吗?你能详细说明存储聚集索引吗? 索引(群集和非群集是否构成n-ary树?)。我无法同时将聚簇索引和非聚簇索引可视化。

1 个答案:

答案 0 :(得分:2)

我是专门谈论InnoDB ...

PRIMARY KEY(如你所说)与数据聚集在一起。整个BTree(数据+ PK)存储在磁盘上的一组块中(不是“主存储器”)。 'leaf'节点包含所有列。

辅助密钥是单独的BTree。在结构上,两个BTree是相同的,除了叶节点中的内容。对于辅助密钥,PRIMARY KEY的副本将放入叶节点。因此,当使用二级索引查找一行(“点查询”)时,有两个BTree下钻 - 一个用于二级索引,一个用于PK。

所有块都在'buffer_pool'中'缓存',因此它们在主内存中有时,但始终在磁盘上保留(迟早)。 (事务日志等)确保“以后”不违反数据始终存在的规则。)

你的两张照片是个不错的开始。然而...

  • 非叶节点链接在一起(如图所示),但它们不一定在磁盘上相邻。插入新行(或新索引条目)时,块可能因为已满而“拆分”。这导致块分散在磁盘周围。
  • 叶节点也链接在一起,但可以分散。
  • 对于Unclustered,嗯,建议你重新开始,考虑到PK问题等。

你需要知道的更高层次,而不是图片试图表达的内容:

  • 点查询向下钻取btree
  • 辅助查找必须执行2次下钻
  • “范围”扫描 - 数据或索引中的任何一个 - 非常有效,因为它们扫描一个块然后通过底层块之间的双向链接移动到(逻辑上)下一个块。因此,它实际上是一个B +树,而不仅仅是一个BTree。
  • (更多关于范围)WHERE clustered_key BETWEEN ...非常有效
  • (更多关于范围)WHERE secondary_key BETWEEN ...非常有效地找到它需要的PK值,但随后变成了一堆(可能的)随机点查询。
  • 所有块都与缓存非常相同。但是(显然?)由于“最近最少使用”的算法,非叶子节点往往存在于缓存中。 (我遗漏了很多细节。)
  • 只能有一个Clustered索引。 (除非您愿意复制所有数据。这已经在除InnoDB之外的几个引擎中完成。)
  • 一个块包含尽可能多的“记录”(数据或索引或非叶子) - 从1到数百个不等。
  • 默认情况下,块为16KB。 (并且不容易改变。)
  • 使用innodb_file_per_table = ON时,给定表的所有BTree都位于单个.ibd'表空间'中。
  • 对于innodb_file_per_table = OFF,所有表的所有BT都存在于一个名为ibdata1的全局“表空间”中。 (再次,过度简化。)

现在为MyISAM:

  • 一个表的数据存在于一个文件(.MYD)中。
  • 一个表的所有索引(包括PRIMARY KEY)都存在于一个文件(.MYI)中
  • 所有索引都是BTrees。 (数据不是。)
  • 索引的叶节点“指向”数据文件。
  • 索引块为1KB。
  • 数据文件只是一个随机访问流。

(还有更多细节。)