为什么Mysql选择B + Tree

本文深入探讨了数据库索引的本质,解析了不同索引结构如HASH表、二叉树、B树及B+树的特点与应用场景,重点讲解了MySQL中InnoDB引擎的B+树索引如何提高查询效率,以及在创建索引时应考虑的因素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

索引的本质

索引是一种数据结构。
分享一个可以观察各种树形结构变化的网站
https://www.cs.usfca.edu/~galles/visualization/BTree.html

HASH表索引

目前mysql数据库支持hash和BTREE两种索引方式
在这里插入图片描述
HASH表索引图:
在这里插入图片描述
对于等值查找HASH索引有天然的优势,只需要HASHCODE方法便可以查找,但是对于范围查询不好匹配。假如有2条数据,第一条hashcode=1,另一条hashcode=1000000,此时使用范围查找,会有很多空值hashcode。
所以MYSQL放弃了HASH表索引结构。

二叉树

在这里插入图片描述
二叉树有很明显的缺陷,当数据主见是int递增的情况下,二叉树会变成一条链表,所以不选择二叉树。

平衡二叉树

在这里插入图片描述
平衡二叉树解决了主键递增情况树变成链表的结果,但是依然有很多问题。
当数据量太多的时候,数高不可控,需要的io操作太多。
从操作系统磁盘交互特性的角度考虑,4K是一页,但是每个磁盘节点的数据不够4K,所以导致磁盘的利用率太低。

B树

在这里插入图片描述

B树又称为多路平衡查找树,有效的解决了磁盘利用率低的问题。因为每个 节点有n个关键词,n+1个数据区,以16K计算的话,在理想状况下关键字为512个,刚好完美利用磁盘。(具体计算为关键词为4个bit,数据区为2k,这里也说不太清,有兴趣可以自行了解一下)
B树也存在一定的问题,就是io操作多,因为当要查找的数据在叶子节点的话每次的磁盘查找会带有数据区的数据,然而这些数据是不需要使用的,MYSQL在B树的基础上做了调整,从而选择了B+树

B+树

在这里插入图片描述

B+树在B树的前提下,只有叶子节点存在数据,根节点和枝节点只有数据的指向,叶子节点采用了左闭合的方式,形成了一个天然的排序,这也就是说为什么order by id DESC效率很高。同样,在排序的时候尽量选用索引列排序防止二次排序。
order by id DESC和order by create_time DESC结果一样,但是前者效率高。
也因为这种左闭合的叶子节点模式,无论是等值查找还是范围查找都非常的效率。

Innodb引擎

在mysql5.5以后,引擎变为Innodb
在这里插入图片描述

这种索引结构如果只需要查询辅助索引的内容,则不需要回表,效率很高。

创建索引字段的选择

一般选择离散度好的字段。离散度好可以理解为字段重复读少的字段。例如性别字段(1:男2:女),字段只有1和2,重复读高,当离散率在15%(记不清了)以下时候,mysql查询会强制不采用此索引。

创建索引

select * from user where name = ?;
select * from user where name = ? and phone = ?;

假如以上2句sql,在公司数据库频繁使用,则只需要创建联合索引即可,不需要针对name字段创建辅助索引。因为会变成冗余索引,导致cup的飙升,由于索引的最左前缀原则,此时创建联合索引即可,会包括辅助索引。联合索引需要注意字段的前后顺序,因为会遵循最左前缀原则。

create index idx_name_phone on user(name,phone);

### MySQL B+Tree 素引工作原理 #### 一、B+Tree 的基本特性 B+Tree 是一种多路搜索树,其设计目的是为了减少磁盘I/O操作次数。与普通的二叉查找树不同,在B+Tree中: - 所有记录节点都位于叶子结点上; - 非叶节点仅保存关键字及其指向子树的指针; - 叶子节点之间存在链表连接,方便范围扫描。 这种结构使得每次访问都能定位到具体的页位置,并且可以快速遍历相邻的数据项[^1]。 #### 二、InnoDB 中 B+Tree 实现特点 在 InnoDB 存储引擎里实现了自己的版本——即所谓的“聚簇索引”。这意味着每张表都有一个唯一的聚集索引(通常是主键),其他辅助索引则会引用这个聚集索引来间接存取实际行数据。当创建一个新的非唯一二级索引时,它实际上是由两部分组成:一部分用于存储该列上的值;另一部分则是对应于这些值所在行的位置信息(也就是主键值)[^4]。 #### 三、查询过程解析 假设有一个基于整数ID建立起来的标准B+Tree索引,当我们执行如下SQL语句 `SELECT * FROM table WHERE id=5;` ,整个检索流程大致如下所示: 1. **根节点读入缓存区** 查询开始前先加载根节点至缓冲池内。 2. **比较并向下层推进** 对当前节点内的所有key进行线性查找,找到第一个大于等于目标id的关键字k_i,接着转向对应的分支继续探索直到达到最底层为止。 3. **命中或未命中的处理** 如果最终落在某个leaf node里面找到了匹配条目,则返回相应结果集给客户端程序;反之如果找不到任何符合条件的结果就报错提示用户不存在这样的记录[^2]. ```sql EXPLAIN SELECT * FROM t_user WHERE user_id = '007'; ``` 上述命令可以帮助开发者查看具体某次select操作所走过的路径以及涉及到哪些index pages.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值