MySQL 的索引是在存储引擎层实现的,不同的存储引擎有不同的索引结构,主要包含以下几种 :
| 索引结构 | 描述 |
|---|---|
| B+Tree索引 | 最常见的索引类型,大部分引擎都支持 B+ 树索引 |
| Hash索引 | 底层数据结构是用哈希表实现的, 只有精确匹配索引列的查询才有效, 不支持范围查询 |
| R-tree(空间索引) | 空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少 |
| Full-text(全文索引) | 是一种通过建立倒排索引,快速匹配文档的方式 |
| 索引结构 | InnoDB | MyISAM | Memory |
|---|---|---|---|
| B+Tree索引 | 支持 | 支持 | 支持 |
| Hash 索引 | 不支持 | 不支持 | 支持 |
| R-Tree 索引 | 不支持 | 支持 | 不支持 |
| Full-text | 5.6版本之后支持 | 支持 | 不支持 |
总结:
等值查询时效率很高,但是不支持范围快速查找,范围查找时还是只能通过扫描全表方式。背景:
二叉树在大部分情况下都可以提高检索速度,但在顺序插入时,会形成一个链表,查询性能大幅度降低。数据量大的情况下,层级较深,检索速度慢。
红黑树可以很好的解决顺序插入的问题,不过在数据量大的情况下,也存在层级较深,检索速度慢的问题。
因为在 MySQL 的 InnoDB 存储引擎一次 IO 会读取的一页(默认一页16K)的数据量,而二叉树一次 IO 有效数据量只有16字节,空间利用率极低。为了最大化利用一次 IO 空间,一个简单的想法是在每个节点存储多个元素,在每个节点尽可能多的存储数据。每个节点可以存储1000个索引(16k/16=1000),这样就将二叉树改造成了多叉树,通过增加树的叉树,将树从高瘦变为矮胖。构建1百万条数据,树的高度只需要2层就可以(1000*1000=1百万),也就是说只需要2次磁盘 IO 就可以查询到数据。磁盘 IO 次数变少了,查询数据的效率也就提高了。
这种数据结构我们称为B树,B树是一种多叉平衡查找树,如下图主要特点:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5lJjduTX-1662625176588)(C:/Users/10642/AppData/Roaming/Typora/typora-user-images/image-20220902091609483.png)]](https://1000bd.com/contentImg/2023/11/05/082830601.png)
缺点:
B+Tree,在 B+Tree 基础上进行了改造。B+Tree 和 B-Tree 最主要的区别在于非叶子节点是否存储数据的问题,即:
只存储键值。叶子节点形成一个单向链表,非叶子节点仅仅起到索引数据的作用,具体的数据都是在叶子节点存放的 。MySQL 索引数据结构对经典的 B+Tree 进行了优化。在原 B+Tree 的基础上,增加一个指向相邻叶子节点的链表指针,即叶子节点之间使用双向指针连接,最底层的叶子节点形成了一个双向有序链表。进一步提高区间访问的性能,利于排序。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-22ofx9o6-1662625176590)(C:/Users/10642/AppData/Roaming/Typora/typora-user-images/image-20220902094930473.png)]](https://1000bd.com/contentImg/2023/11/05/082830585.png)
MySQL 对 B+Tree 进行了优化之后,可以保证等值和范围查询的快速查找。
面试题
- 为什么 InnoDB 存储引擎选择使用 B+Tree 索引结构?(B+Tree 的优点?)
- 相对于二叉树,层级更少,搜索效率高。
- 对于 B-Tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针也跟着减少,要同样保存大量数据,只能增加树的高度,导致性能降低。
- 相对于 Hash 索引,B+Tree 支持范围匹配及排序操作。