本文深度参考Mysql45讲
索引作用
加速提高查询数据的作用,就像目录一样。
索引模型
构建索引时间复杂度
查询方式:等值查询,区间查询时间复杂度,空间复杂度
哈希模型
- 索引构建
通过key哈希值构建索引,如果发生冲突的话,采用拉链表的模式。
构建索引效率,o1 - 查询效率
等值查询: o1查询
范围查询: 效率巨低 - 删除效率 o1
- 应用场景
等值查询的场景
有序数组
- 索引构建
key值有序增加
构建索引效率 o(n),需要移动后面所有的记录 - 查询效率
等值查询: o(logn)查询
范围查询: o(logn) - 删除效率 o(n)
- 应用场景
静态数据,比如历史记录信息
搜索树
树型结构保存索引
采用多叉树的原因在于索引可能存在磁盘中,多叉树层级较低,可以减少和磁盘的交互。Innodb N叉树的N为1200
- 索引构建 o(logn)
- 查询效率 o(logn)
- 删除效率 o(logn)
本身没有问题,只不过是随着写的变多了,叶子结点存储可能更离散。
跳表
结合树和有序数组的优点,也是采用分层结构,每一层有序。
它比搜索树点在于增加删除时,比较简单只影响相邻节点,不涉及子树的调整。
和其他相比,范围查找具有优势。在最底层找到范围小值,顺序查找即可。搜索树(B树)需要中序遍历(搜索树叶子节点也可能有有序链表)。
- 索引构建 o(logn)
- 查询效率 o(logn)
- 删除效率 o(logn)
LSM树
前面的结构都是基于结果的存储,lsm树(log structured merge tree)存的是日志记录。
- 参考多级缓存的结构,先写缓存,(再排序)再刷磁盘。这样随机性变成一定程度的顺序写。
- 读取时内存和磁盘合并读取,磁盘上也需要多路归并。
WAL是为了防止内存数据丢失,先进行顺序写磁盘。
InnoDB的索引
InnoDB索引使用B+树,搜索树+叶子指针
主键索引
主键索引同聚簇索引,叶子结点存储的是整行数据
非主键索引
非主键索引的叶子结点存储的是主键的值,也称为二级索引。查询非主键索引需要查询主键索引才可以得到具体的记录。这个叫做回表。
索引的维护
- 插入/删除新的记录时,需要和主键索引的构造一致,保持有序。
主键索引中最下层是具体记录,所以说新的记录插入位置需要和主键索引保持一致。使用自增主键时,能保证新插入数据是增量的。
- 主键长度要小
二级索引的叶子结点是主键索引,所以要小一点。
只有kv场景,只有一个索引,这时候可以不考虑其他索引大小问题。
索引查询优化
思路就是对于查询
如何构建索引树,使得可以减少回表。
如何复用已有的索引树,减少空间占用。
覆盖索引
查询的结果直接在索引树上,这样就不需要回表了。但是需要增加空间。
最左前缀原则
索引的排序是按照key值字典序构造的,所以查询时遇到like A%,也可以使用已有的索引进行加速。
索引下推
查询时,不满足最左前缀的部分,也可以在查询索引时进行过滤,减少回表次数。
比如说(A,B)联合索引,查询A like “张%” and B = 10 and is male=1, 那么可以查索引时,进行判断,减少回表次数。