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

Where clustered and unclustered index of B+ tree are saved?

目前我正在阅读 B+ Tree 基础知识,并对 space 聚集索引和非聚集索引的分配感到困惑。

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

现在假设我们有一个 table (id, name, class) 我在 nameclass我怀疑非聚集索引将存储在哪里?以及如何搜索像

这样的 query
select id, name, class from table where id = 3, name='Leo' and class='10'

我的假设:

你觉得我的假设对吗?您能否详细说明有关存储聚集索引的信息? 这两个索引(聚集和非聚集形成一个 n-ary 树?)。我无法同时显示聚簇索引和非聚簇索引。

我说的是 InnoDB...

PRIMARY KEY(如您所说)与数据聚类。整个 BTree(数据 + PK)存储在磁盘上的一组块中(不是 'main memory')。 'leaf' 节点包含所有列。

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

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

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

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

您需要了解比图片试图传达的更高层次的信息:

  • 一个点查询下钻一个btree
  • 二次查找必须进行 2 次向下钻取
  • "Range" 扫描——无论是数据还是索引——都非常有效,因为它们扫描一个块,然后通过双向 link 在底层的块之间。因此,它实际上是一个B+Tree,而不仅仅是一个BTree。
  • (范围更多)WHERE clustered_key BETWEEN ... 非常有效
  • (更多关于范围)WHERE secondary_key BETWEEN ... 在查找所需的 PK 值方面非常有效,但随后会变成一堆(可能)随机点查询。
  • 所有块对于缓存来说几乎都是等价的。但是(显然?)由于 "least recently used" 算法,非叶节点倾向于存在于缓存中。 (我遗漏了很多细节。)
  • 聚簇索引只能有一个。 (除非您愿意复制所有数据。这已经在 InnoDB 以外的几个引擎中完成了。)
  • 一个块包含尽可能多的 'records'(数据或索引或非叶),从 1 到数百不等。
  • 默认情况下,一个块为 16KB。 (而且不容易改变。)
  • 在 innodb_file_per_table=ON 的情况下,给定 table 的所有 BTree 都存在于单个 .ibd 'tablespace'.
  • 在 innodb_file_per_table=OFF 的情况下,所有 table 的所有 BTree 都位于一个名为 ibdata1 的全局 'tablespace' 中。 (再次,过度简化。)

现在用于 MyISAM:

  • 一个 table 的数据保存在文件 (.MYD) 中。
  • 一个 table 的所有索引(包括 PRIMARY KEY)都存在于文件 (.MYI)
  • 所有的索引都是BTrees。 (数据不是。)
  • 索引的叶节点'point'进入数据文件。
  • 索引块为 1KB。
  • 数据文件只是一个随机访问流。

(还有很多细节。)