Mysql索引设计

本文是根据微信知识星球沈剑老师的文章的总结与感悟

  • 数据库设计索引的原因
  • 索引结构为什么要设计成树型,而不是更快的hash
  • 数据库索引为什么使用B+树?
  • 总结

数据库设计索引的原因

类比于书本首页的索引,给全书一个指向

索引结构为什么要设计成树型,而不是更快的hash

加速查找速度的数据结构,常见的有两类:
(1)哈希,例如HashMap,查询/插入/修改/删除的平均时间复杂度都是O(1)
(2)树,例如平衡二叉搜索树,查询/插入/修改/删除的平均时间复杂度都是O(lg(n))
可以看到,不管是读请求,还是写请求,哈希类型的索引,都要比树型的索引更快一些,那为什么,索引结构要设计成树型呢?
解答:
索引设计成树形,和SQL的需求相关。
对于这样一个单行查询的SQL需求:
select * from t where name=”shenjian”;
确实是哈希索引更快,因为每次都只查询一条记录。但是对于排序查询的SQL需求:分组,排序,比较,哈希型的索引,时间复杂度会退化为O(n),而树型的“有序”特性,依然能够保持O(log(n)) 的高效率。
InnoDB并不支持哈希索引。

数据库索引为什么使用B+树?

看下几种树的样子
二叉搜索树
Mysql索引设计_第1张图片
不适合做索引的原因
(1)当数据量大的时候,树的高度会比较高,数据量大的时候,查询会比较慢;
(2)每个节点只存储一个记录,可能导致一次查询有很多次磁盘IO;

B树
Mysql索引设计_第2张图片

B树,如上图,它的特点是:
(1)不再是二叉搜索,而是m叉搜索;
(2)叶子节点,非叶子节点,都存储数据;
(3)中序遍历,可以获得所有节点;
B树被作为实现索引的数据结构被创造出来,是因为它能够完美的利用“局部性原理”。

什么是局部性原理?
(1)内存读写比磁盘读写快很多
(2)B+树中每个非叶节点没有指向某个关键字具体信息的指针,所以每一个节点可以存放更多的关键字数量,即一次性读入内存所需要查找的关键字也就越多
(3)磁盘预读:磁盘读写并不是按需读取,而是按页预读,一次会读一页的数据,每次加载更多的数据,如果未来要读取的数据就在这一页中,可以避免未来的磁盘IO,提高效率,通常,一页数据是4K。
(4)局部性原理:软件设计要尽量遵循“数据读取集中”与“使用到一个数据,大概率会使用其附近的数据”,这样磁盘预读能充分提高磁盘IO;

B树为何适合做索引?
(1)由于是m分叉的,高度能够大大降低;
(2)每个节点可以存储j个记录,如果将节点大小设置为页大小,例如4K,相邻的数据预先存储,就能够充分的利用预读的特性,极大减少磁盘IO;

B+树
Mysql索引设计_第3张图片
B+树,如上图,仍是m叉搜索树,在B树的基础上,做了一些改进:
结构上
(1) B树中关键字集合分布在整棵树中,叶节点中不包含任何关键字信息,而B+树关键字集合分布在叶子结点中
(2) B树中任何一个关键字只出现在一个结点中,而B+树中的关键字必须出现在叶节点中,也可能在非叶结点中重复出现;

性能上(B+树还比B树更适合实际应用中操作系统的文件索引)
(1) 不同于B树只适合随机检索,B+树同时支持随机检索和顺序检索;
B+树内部结点比B树小,盘块能容纳的结点中关键字数量更多,一次性读入内存中可以查找的关键字也就越多,相对的,IO读写次数也就降低了。而IO读写次数是影响索引检索效率的最大因素。

B+树的查询效率更加稳定:
(1) B树搜索有可能会在非叶子结点结束,越靠近根节点的记录查找时间越短,只要找到关键字即可确定记录的存在,其性能等价于在关键字全集内做一次二分查找。
(2) B+树中,顺序检索比较明显,随机检索时,任何关键字的查找都必须走一条从根节点到叶节点的路,所有关键字的查找路径长度相同,导致每一个关键字的查询效率相当。B+树的叶子节点使用指针顺序连接在一起,只要遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作(或者说效率太低)。

总结

数据库索引用于加速查询

虽然哈希索引是O(1),树索引是O(log(n)),但SQL有很多“有序”需求,故数据库使用树型索引

InnoDB不支持哈希索引

数据预读的思路是:磁盘读写并不是按需读取,而是按页预读,一次会读一页的数据,每次加载更多的数据,以便未来减少磁盘IO

局部性原理:软件设计要尽量遵循“数据读取集中”与“使用到一个数据,大概率会使用其附近的数据”,这样磁盘预读能充分提高磁盘IO

数据库的索引最常用B+树:

(1)很适合磁盘存储,能够充分利用局部性原理,磁盘预读;

(2)很低的树高度,能够存储大量数据;

(3)索引本身占用的内存很小;

(4)能够很好的支持单点查询,范围查询,有序性查询;

你可能感兴趣的:(Mysql索引设计)