B树
很多存储引擎使用的时B-Tree,即每一个叶子节点都包含指向下一个叶子节点的指针,从而方便叶子节点的范围遍历。
底层的存储引擎可能使用不同的存储结构。存储引擎以不同的方式使用B-Tree索引,性能也各不相同,各有优劣。
B-Tree
B+Tree
B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构,InnoDB存储引擎就是用B+Tree实现其索引结构。
MyISAM使用前缀压缩技术使得索引更小,但是InnoDB则按照元数据格式进行存储。
MyISAM索引通过数据的物理位置引用被索引的行,而InnoDB则根据主键引用被索引的行。
索引对多个值进行排序的依据是CREAT TABLE语句中定义索引时列的顺序。
B+Tree对索引列时顺序组织存储的,所以很适合查找范围数据。
可以使用B+Tree索引的查询类型
B+Tree索引适用于全键值、键值范围或键前缀查找。其中键前缀查找只适用于根据最左前缀的查找。
- 全值匹配
- 匹配最左前缀
- 匹配列前缀
- 精确匹配某一列并范围匹配另外一列
- 只访问索引的查询:查询只需要访问索引,无需访问数据行。
B+Tree索引的限制:
- 若不是按照
索引的最左列开始查询找,则无法使用索引; - 不能跳过索引中的列;
- 如果查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找。
有些限制并不是B+Tree本身导致的,而是MySQL优化器和存储引擎使用的索引的方式导致的。
为什么使用 B+Tree
-
B+Tree更适合外部存储,由于内节点无 data 域,一个结点可以存储更多的内结点,每个节点能索引的范围更大更精确,也意味着B+Tree单次磁盘IO的信息量大于B-Tree,I/O效率更高。 -
Mysql是一种关系型数据库,区间访问是常见的一种情况,
B+Tree叶节点增加的链指针,加强了区间访问性,可使用在范围区间查询等,而B-Tree每个节点 key 和 data 在一起,则无法区间查找。 -
B-Tree的非叶子结点会存放数据,而B+Tree的非叶子结点不存放数据,只存放关键字,这样同一个结点,B+Tree的结点能形成的叉数越多,那么存储一定数量的数据,B+Tree的高度越小,那么插入、查找、删除的性能会越高。(B-Tree和B+Tree的插入、查找、删除的时间复杂度与树的高度成正相关)。
MySQL 中 Innodb 存储引擎存储数据的最小单元是页,一页的大小默认是 16KB(可修改)
MariaDB [(none)]> show variables like 'innodb_page_size';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
1 row in set (0.001 sec)
在读数据时,也是以页为单位将数据从磁盘加载进内存当中,每从磁盘中读取一个页,就会发生一次磁盘 IO。也就是说,在查找数据时,每遍历一个结点,就意味着读取一个数据页,也就是发生一次 IO。
参考
[1] 数据结构动态展示 www.cs.usfca.edu/~galles/vis…
[2] 以B tree和B+ tree的区别来分析mysql索引实现 www.jianshu.com/p/0371c9569…
[3] 由 B-/B+树看 MySQL索引结构 segmentfault.com/a/119000000…