1. 索引的本质是什么
索引的本质是一种排好序的数据结构。
它就好比字典中的目录。
2. 索引的分类
索引的分类要看是什么维度。
如果是从数据库功能的维度来划分的,如下:
如果是从数据结构的维度来划分的,如下:
Hash 索引
Hash 索引是比较常见的一种索引,他的单条记录查询的效率很高,时间复杂度为1。
但是,Hash索引并不是最常用的数据库索引类型,尤其是我们常用的Mysql Innodb引擎就是不支持hash索引的。
因为存储引擎都会为每一行计算一个hash码,hash码都是比较小的,
并且不同键值行的hash码通常是不一样的,hash索引中存储的就是Hash码,
hash 码彼此之间是没有规律的,且 Hash 操作并不能保证顺序性,
所以值相近的两个数据,Hash值相差很远,被分到不同的桶中。
二叉树
一个节点只能有两个子节点。即度不超过2
二叉树的时间复杂度为 O(n)
左子节点 小于 本节点,右子节点 大于 本节点
二叉树的特点:
磁盘的IO由树高决定
B树(二三树)
B树的结构每个节点中不仅包含数据的 key 值,还有 data 值
见下图
如果 data 比较大,会导致每个节点的 key 存储的较少,
当数据量较大的时候,同样会导致B树很深,从而增加了磁盘 IO 的次数,进而影响查询效率。
B+树
MySQL 中最常用的索引的数据结构是 B+ 树,它有以下特点:
1. 在 B+ 树中,所有数据记录节点都是按照键值的大小存放在同一层的叶子节点上,
而非叶子结点只存储key的信息,这样可以大大减少每个节点的存储的key的数量,降低B+ 树的高度
2. B+ 树叶子节点的关键字从小到大有序排列,左边结尾数据都会保存右边节点开始数据的指针。
3. B+ 树的层级更少:相较于 B 树 B+ 每个非叶子节点存储的关键字数更多,
树的层级更少所以查询数据更快
4. B+ 树查询速度更稳定:B+ 所有关键字数据地址都存在叶子节点上,
所以每次查找的次数都相同所以查询速度要比B树更稳定;
5. B+ 树天然具备排序功能:B+ 树所有的叶子节点数据构成了一个有序链表,
在查询大小区间的数据时候更方便,数据紧密性很高,缓存的命中率也会比B树高。
6. B+ 树全节点遍历更快:B+ 树遍历整棵树只需要遍历所有的叶子节点即可,
而不需要像 B 树一样需要对每一层进行遍历,这有利于数据库做全表扫描。
3. 何时使用索引
MySQL每次查询只使用一个索引。
与其说是“数据库查询只能用到一个索引”,倒不如说,和全表扫描比起来,
去分析两个索引B+树更加耗费时间。
所以where A=a and B=b这种查询使用(A,B)的组合索引最佳,
B+树根据(A,B)来排序。
使用索引的场景:
a. 主键,unique字段
b. 和其他表做连接的字段需要加索引
c. 在where里使用>,≥,=,<,≤,is null和between等字段
d. 使用不以通配符开始的like,where A like 'China%'
e. 聚集函数MIN(),MAX()中的字段
f. order by和group by字段
4. 何时不使用索引
不使用索引的场景:
a. 表记录太少
b. 数据重复且分布平均的字段(只有很少数据值的列)
c. 经常插入、删除、修改的表要减少索引
d. text,image等类型不应该建立索引,这些列的数据量大
假如text前10个字符唯一,也可以对text前10个字符建立索引
e. MySQL能估计出全表扫描比使用索引更快时,不使用索引
5. 索引何时失效
索引失效的场景:
a. 组合索引未使用最左前缀,例如组合索引(A,B),where B=b不会使用索引
b. like未使用最左前缀,where A like '%Sheep'
c. 搜索一个索引而在另一个索引上做order by,where A=a order by B,
只使用A上的索引,因为查询只使用一个索引
d. or会使索引失效。如果查询字段相同,也可以使用索引。
(eg: where A=a1 or A=a2(生效),where A=a or B=b(失效))
e. 如果列类型是字符串,要使用引号
(eg: where A='Sheep',否则索引失效(会进行类型转换))
f. 在索引列上的操作,函数(upper()等)、or、!=(<>)、not in等