B+树索引
B树是一种多路搜索树,在数据库、文件系统中常用于索引结构,它是 B+ 树的“祖先”,但现在用得更少。下面是它的主要特点:
B 树的核心特点(以阶为 m 的 B 树为例)
特点 | 说明 |
---|---|
多叉结构 | 每个节点最多有 m 个子节点,m 是树的阶。 |
有序性 | 所有节点的 key 有序,子树分布在 key 的两边。 |
自平衡 | 插入/删除后自动保持平衡(高度相同)。 |
所有节点都存数据 | 每个节点都存 key 和 value。 |
B+ 树是一种多路搜索树,是 B 树的变种,常用于数据库和文件系统中,特别适合磁盘存储和范围查询,InnoDB就是采用的B+树。
B+ 树的核心特点:
1. 所有数据只存储在叶子节点
- 非叶子节点(也叫“内部节点”)只存 索引 key(右侧子节点的最小key),用于导航,不存实际数据。
- 所有完整的记录/行数据都在叶子节点。
2. 叶子节点之间通过链表相连
- 形成有序链表,支持快速的区间(范围)查询。
3. 每个节点存多个 key 和指针
- 一般一个节点最多可以存
m-1
个 key 和m
个子指针。
B+ 树相对 B 树的主要改进:
方面 | B 树 | B+ 树 | 改进效果/原因 |
---|---|---|---|
数据存储 | 关键字和数据同时存储在所有节点 | 关键字只存储在内部节点,数据只存在叶子节点 | 内部节点更小,能存更多 key,降低树高度,查询更快 |
叶子节点链表 | 没有叶子节点链表 | 叶子节点通过链表串联起来 | 支持高效范围查询(顺序遍历叶子节点即可) |
查询效率 | 可能在任何节点找到数据 | 必须到叶子节点才能找到数据 | 统一访问叶子节点,范围查询方便,磁盘读写更顺序 |
范围扫描 | 复杂 | 简单且高效 | 叶子节点顺序连接,扫描时避免多次回溯和随机访问 |
节点大小 | 节点存数据较大 | 内部节点更小,叶子节点存完整数据 | 内部节点小,有助于减少磁盘IO,提高缓存利用率 |
为什么数据库用 B+ 树?
因为磁盘 I/O 非常慢,而 B+ 树专门为减少磁盘访问次数设计:
方面 | B+ 树 | 红黑树 |
---|---|---|
节点大小 | 大,匹配磁盘页 | 小,单个元素 |
树高 | 低,多路树 | 较高,二叉树 |
磁盘 IO 次数 | 少,顺序读取,预读好 | 多,随机访问 |
范围查询 | 高效,叶子链表支持顺序遍历 | 低效,需要中序遍历 |
适用场景 | 磁盘索引结构,数据库索引 | 内存数据结构,平衡二叉树 |
在 InnoDB 中的作用
- 主键索引(聚簇索引):B+ 树的叶子节点就是整行数据;
- 二级索引(非聚簇索引):叶子节点存索引列 + 主键值。
二级索引查找到主键值后要回表查询行数据。
MyISAM
- MyISAM 是 MySQL 早期的默认存储引擎,基于 ISAM(Indexed Sequential Access Method)改进而来。
- 主要用于读操作多,写操作相对较少的场景。
- 不支持事务(无redolog和undolog),也不支持行级锁,只支持表级锁。
MyISAM表数据和索引分别存储在.MYD和.MYI文件中
MYI使用B+树记录索引,存储数据MYD的偏移地址
思考
思考:为什么二级索引不采用聚簇索引?
- 如果每个索引都把数据拷贝一遍,磁盘和内存成本太高。
- 多个“聚簇”会有多个版本的行数据,不一致不好维护。
- 这违背了“唯一数据源”的设计理念。
思考:创建表的时候,没有设置主键,那存储引擎会怎么办?
InnoDB要求表必须有主键(MyISAM可以没有)。如果没有显式指定,则MysQL系统会自动选择一个可以非空且唯一标识数据记录的列作为主键。如果不存在这种列,则MysQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整型。
HASH索引
Hash 索引 是一种基于哈希表的数据结构,通过对索引列的值计算哈希函数,快速定位数据的位置。
特性 | 说明 |
---|---|
访问速度快 | 哈希查找是 O(1) 的复杂度,查找非常快 |
不支持范围查询 | 因为哈希表是无序的,不能用来做 BETWEEN、<、> 查询 |
不支持排序 | 不能用于 ORDER BY,因为没有顺序 |
不支持模糊匹配 | 不支持LIKE ‘%xxx%’,除非是以常量开头的前缀匹配(视实现而定) |
有哈希冲突 | 不同的值可能得到相同的哈希值(冲突),需要链式或开放寻址法解决 |
使用 Hash 索引的局限
- 不适合多种 SQL 查询条件(如范围、排序)
- 对内存要求高
- 不支持联合索引的范围查询
- 遇到哈希冲突会退化成链表查找,性能下降
联合索引的存储结构
联合索引遵循 最左前缀(最左列)匹配原则,即只能从最左边开始依次生效。
如图联合主键索引,先根据name进行排序,再根据age进行排序,最后根据position进行排序