B+树的聚簇索引和非聚簇索引保存在哪里?
Where clustered and unclustered index of B+ tree are saved?
目前我正在阅读 B+ Tree
基础知识,并对 space 聚集索引和非聚集索引的分配感到困惑。
当我们在 B+ tree
上创建聚簇索引时,索引存储在主内存中,叶子包含指向实际块的数据指针。块存储在磁盘中,块包含记录。
- 通常聚簇索引是在主键上创建的
- 聚簇索引只能有一个
现在假设我们有一个 table (id, name, class) 我在 name
和 class
。 我怀疑非聚集索引将存储在哪里?以及如何搜索像
这样的 query
select id, name, class from table where id = 3, name='Leo' and class='10'
我的假设:
- 由于id字段是主键所以首先使用聚集索引将id = 3
- 现在使用
name
和 class
上的非聚集索引,我们将找到剩余的字段
你觉得我的假设对吗?您能否详细说明有关存储聚集索引的信息? 这两个索引(聚集和非聚集形成一个 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。
- 数据文件只是一个随机访问流。
(还有很多细节。)
目前我正在阅读 B+ Tree
基础知识,并对 space 聚集索引和非聚集索引的分配感到困惑。
当我们在 B+ tree
上创建聚簇索引时,索引存储在主内存中,叶子包含指向实际块的数据指针。块存储在磁盘中,块包含记录。
- 通常聚簇索引是在主键上创建的
- 聚簇索引只能有一个
现在假设我们有一个 table (id, name, class) 我在 name
和 class
。 我怀疑非聚集索引将存储在哪里?以及如何搜索像
query
select id, name, class from table where id = 3, name='Leo' and class='10'
我的假设:
- 由于id字段是主键所以首先使用聚集索引将id = 3
- 现在使用
name
和class
上的非聚集索引,我们将找到剩余的字段
你觉得我的假设对吗?您能否详细说明有关存储聚集索引的信息? 这两个索引(聚集和非聚集形成一个 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。
- 数据文件只是一个随机访问流。
(还有很多细节。)