3.5 mysql索引数据结构
说明:本文讨论的知识点都是基于mysql InnoDB存储引擎。
一、索引是什么?
在mysql里索引是对数据库表中一列或多列的值进行排序的一种数据存储结构。它可以明显的提高查询效率。
二、索引的结构
1、二分查找法也叫折半查找
从上述数组中查找48这条记录,可分三步完成。
2、二叉查找树
在二叉树中左子树的键值总是小于根的键值,右子树的键值总是大于根的键值。
二叉查找树1
从上述二叉查找树里查找键值5的过程:
先找到根6,5小于6,因此查找6的左子树,找到3,5大于3,所以在找3的右子树,从而找到5,一共三次查找。二叉查找树2
而上图也是一个二叉查找树,但是它的查找效率和顺序查找差不多。因此若想最大性能的构造一棵二叉查找树,需要这棵查找树是平衡的。
3、平衡二叉树
平衡二叉树首先需要满足二叉查找树的规则,其次需要满足任意两个节点的两个子树的高度差为1。
二叉查找树1图中的二叉树就是平衡二叉树。
平衡二叉树的查询速度很快,但是要维护平衡的代价很大,需要进行一次或者多次的左旋或右旋来得到插入和更新后树的平衡性。
如:二叉查找树1图中插入9,要保持平衡性,需要进行左旋,得到下图:
平衡二叉树
4、b+树
b+tree是为磁盘或其他直接存取辅助设备设计的一种平衡查找树。
在b+树中所有的记录节点都是按照键值的大小顺序存放在同一层的叶子节点上。由各个叶子节点的指针进行连接。
以下是一个3度,每页可存放2条记录的b+树:b+树1
b+树的插入规则:
按照上述规则在b+树1图中插入4,及插入10后的结果:
5、b+树索引
b+树索引的本质就是b+树在数据库中的实现。
磁盘扇区、文件系统、InnoDB 存储引擎都有各自的最小存储单元,InnoDB默认是16k,也可以自定义默认大小。InnoDB的最小存储单元是页。
b+树的每一个节点都会存储在页中,mysql在查询数据过程中会以页为单位把数据加载到内存中,然后进行比对数据。
5.1、聚集索引就是按照每张表的主键构造一个b+树,同时叶子节点中存放的即为整张表的行记录数据。
如果表没有指定主键,那么InnoDB会选择一个非空唯一索引作为构造b+树的键值,如果没有会隐式定义一个主键。
由于实际的数据页只能按照一棵b+树进行排序,因此每张表只能拥有一个聚集索引。
5.2、非聚集索引(辅助索引)
叶子节点并不包含行记录的全部数据,叶子节点除了包含键值以外,InnoDB非聚集索引每个叶子节点中的行数据是聚集索引键。
因此辅助索引查找数据的过程中会有两次索引过程,先从辅助索引中查找出聚集索引键,而后在从聚集索引中查处具体的行数据,这个过程也可称为回表。
!三、索引的应用类型
1、覆盖索引即从辅助索引中就可以查询到的记录,而不需要查询聚集索引中的记录,
优点是辅助索引不包含整行记录的所有信息,其大小要远小于聚集索引,可以减少io操作。
案例1:当一张表里有聚集索引和辅助索引时,在count数据的时候,innodb会自动优化使用辅助索引,而不是使用聚集索引。
2、其他应用索引
唯一索引、联合索引等都属于辅助索引。可以自己介绍。
案例2:优化器不使用索引的情况
当有些时候explain进行sql语句分析时,发现没有使用索引去查询数据,而是直接进行全表扫描来得到数据。
案例复现过程:
表结构:
表索引情况:
执行sql:SELECT id,order_id,create_time from dc_order_details where order_id >10000 and order_id < 102000
执行计划:
综上可以看出,执行引擎并没有使用我们给order_id建立的索引进行查询,而是直接扫描全部数据。
原因:我们想要查询的是id,order_id,create_time,显然如果只查询辅助索引是不足以满足需求,那么就需要通过二次索引查询出整行记录,
虽然order_id索引是顺序放的,但是在二次索引的过程是无序的,因此变成了离散读操作,
这时如果读取的数据量小,优化器还是会选择辅助索引,但是当访问的数据大到整个数据表的20%左右时,
优化器会选择上述的方式进行数据查询,也就是扫描聚集索引。因为顺序读要快于离散读。
附:以上数据结构演示网址
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html