开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 7 天,点击查看活动详情
索引介绍
索引是存储引擎用于快速找到记录的一种数据结构。是对查询性能优化最有效的手段了。
索引的数据结构
索引底层的数据结构有很多的类型,常见的有:B 树、B+ 树、Hash、有序数据、红黑树等。
哈希索引
简介
哈希索引(hash index) 基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。「类似于 Java 中的 HashMap 」数据很多的情况下,不可避免的会出现哈希码一样的情况,处理这种情况是拉出一个链表。
优缺点
数据结构的特性决定了它的使用限制。
- 哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行(比如覆盖索引,避免回表就不行)。
- 数据存放不是按照索引顺序存储,不能用于排序。当然也不能用于范围查找
- 不支持部分索引列匹配查找,以为它始终是使用索引列的全部内容来计算哈希值的,比如(a,b)建立哈希索引,如果只有 a ,则无法使用索引。
- 冲突很多的情况下只能挨个遍历链表。「这里可参考 HashMap,它的链表过长会转红黑树」。而且维护的代码也很高。
适用场景
哈希表这种结构适用于只有等值查询的场景。
在 MySQL 中,只有 Memory 引擎显示支持哈希索引。
有序数组
简介
数组的结构就是连续的内存空间,有序就是排序好的,基于下标查找 O(1) 时间复杂度,不适用于中间删除和增加。
优缺点
- 支持范围查找,使用二分法
- 不能经常性的增加删除,会挪动很多空间
适用场景
适用于静态存储引擎, 比如保存以前某个城市的某一年的人口。不会再修改的数据。
B+Tree 索引
我们一般说的索引都是 B+ 树索引。MySQL 默认的存储引擎是 InnoDB ,InnoDB 默认的索引是 B+ 树。
- B+ 树只有叶子节点存放 key 和 data ,其他节点只存放 key。
- B + 树的叶子节点有一条引用链指向与它相邻的叶子节点。
- B + 树的检索效率很稳定,任何查找都是从根节点到叶子节点的过程。
具体的 B+ 树结构以及在 MySQL 中使用的详情还有待深入学习,先挖个坑。
索引的类型
主键索引
在 InnoDB 中,主键索引也叫聚簇索引(clustered index)。数据库的主键列使用的就是主键索引。
一张数据库表只能有一个主键,并且主键不能为 null,不能重复。下面你虽然选了两个主键,但是为你创建的是联合主键,所以还是只有一个主键。
在 MySQL InnoDB 中,没有显示指定主键的时,InnoDB 会选择第一个唯一非空的索引代替,如果也不存在这样的索引,那么 InnoDB 会隐士定义一个主键。
非主键索引
在 InnoDB 中,非主键索引也叫二级索引(secondary index)。唯一索引、普通索引、前缀索引等都属于二级索引。
- 唯一索引:数据不能重复,允许数据为 NULL ,主要不是为了查询效率,而是保证数据唯一性
- 普通索引:运行数据重复和NULL,单纯为了查询快
- 前缀索引:只适用于字符串类型。为了节省空间,因为只需要创建前几个字符作为索引。
主键索引 vs 非主键索引
基于这两种索引查询有什么区别?
select * from T where ID = 500 ID 是主键
select * from T where k = 5 k 是普通索引
- 基于主键索引,只需要搜索 ID 这颗 B+ 树
- 基于非主键索引,先搜索 k 这颗索引树,得到主键值,再到 ID 索引树搜索一次,这个过程称为回表。
也就是非主键索引的查询需要多扫描一棵索引树。
聚簇索引 vs 非聚簇索引
聚簇索引不是一种单独的索引类型,而是一种数据存储方式。InnoDB 中的聚簇索引就是叶子节点既保存了索引也保存了数据行。 所以主键索引就属于聚簇索引。
非聚簇索引是索引结构和数据分开存放的的索引,二级索引就属于非聚簇索引。
覆盖索引
上面我们提到了回表:当使用二级索引查询的时候,需要回表。那么是否可以避免回表呢?也就是说索引的值‘覆盖’了我们的查询需求,我们就称为覆盖索引。也是常用的优化手段。
最左前缀索引
B+ 树可以利用索引的“最左前缀”来定位记录。一般建立一个联合索引,可以通过调整顺序就可以少维护一个索引。比如说 (a,b)联合索引,此时就不需要再单独建立一个 a 索引了。
索引下推
可以在非聚簇索引遍历过程中,对索引包含的字段先做判断,过滤掉不符合条件的记录,减少回表次数。
总结
目前 InnoDB 中常用的索引理论知识整理了下。还需继续学习:
- B+ 树结构以及在 MySQL 中的具体使用。
参考
《高性能 MySQL 第三版》