mysql基于innodb引擎的索引的见解
本篇文章主要是整合我对mysql数据库的索引的一些理解:
在mysql数据库的优化中,索引肯定是第一个考虑的方法,因为我们要考虑如何使用索引去优化查询,往下推,虽然索引能够好的去优化查询的时间,但是索引不是越多越好,我们知道索引也是占用磁盘空间的,太多的索引插入更新数据会导致耗费大量的时间,如果你想很自如的使用索引进行优化,那肯定得好好了解索引的机制,原理,数据结构。
一句话简单来说,索引的出现其实就是为了提高数据查询的效率,就像书的目录一样。
索引的常见模型
索引的出现是为了提高查询效率,但是实现索引的方式却有很多种,数据库的数据模型一般是哈希表,有序数组,二叉树
哈希表是以key-value形式存储的,单个查询可以很快,但是对于范围查询就很慢,很麻烦。
于是有序数组对单个查询和范围查询都很优秀,因为它是连续的有序的线性排列,但是更新的话可能需要移动大量的数据,成本很高。这个时候就有二叉树,一般有二叉搜索树,左儿子小于根节点,右儿子大于根节点,时间复杂度log(n),但是二叉树当数据量很大的时候,放在磁盘中会占很多磁盘,因为二叉只有2个,因此如果是n叉树就可以解决这个问题,例如1500的叉树4深度就是1500的3的平方。mysql的innodb采取的b+树排列,b+树是按行排列的。
(在这里我并没有详细介绍树,二叉搜索树,b树,b+树等,如果想知道可以看下面我推荐的一篇文章,就知道为什么用b+树而不是其他树了)
InnoDB 的索引模型
在InnoDB中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表。又因为前面我们提到的,InnoDB使用了B+树索引模型,所以数据都是存储在B+树中的。
索引的类型有主键索引(例如id为主键)和非主键索引(普通索引,联合索引,唯一索引),主键索引的叶子节点存的是整行的数据(聚簇索引),非主键索引的叶子节点内容是主键的值(二级索引),也就是说主键索引是一棵树,而非主键索引是另外一颗树,如果使用非主键索引去查询,我们要先查询非主键索引这棵树去找到主键值,然后再去主键索引的树查询要的数据,这种情况称为回表,因为一般情况下查询主键索引会比普通索引来的快,如下图(有点难看,见谅)
覆盖索引
这个时候为什么说是一般呢?因为有时候我们并不需要去回表,当我们使用非主键索引查询的时候,如果我们的sql是这样的呢?
select id from user where user_name=?(user_name是普通索引,id是主键索引)
这样我们在第一颗树就已经拿到id了,就不需要去回表,普通索引“覆盖了”我们的查询需求,我们称为覆盖索引。
如果查询条件使用的是普通索引(或是联合索引的最左原则字段),查询结果是联合索引的字段或是主键,不用回表操作,直接返回结果,减少IO磁盘读写读取正行数据。
存在二次索引比主键索引快的结果吗?存在。
如果现在有一个高频请求,要根据市民的身份证号查询他的姓名,这个时候给身份证号和姓名加上联合索引就有意义了。它可以在这个高频请求上用到覆盖索引,不再需要回表查整行记录,减少语句的执行时间。(既通过联合索引的第一个身份证查到他的姓名,不需要回表)
由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。
索引下堆
上面讲到了一个联合索引的好处,如果我们存在对表的数据查询高频率的通过多个条件查询就可以建立联合索引,组合索引的作用呢就是在查询非主键索引时先判断多个条件满足的情况(排除掉其他不满足情况的条件)再去回表,可以减少回表数。
最左前缀原则
B+树这种索引结构,可以利用索引的“最左前缀”,来定位记录。
这个最左前缀可以是联合索引的最左N个字段,也可以是字符串索引的最左M个字符。
例如 select id from where user_name like '黄%';(字符串索引最左%)
select id from where user_name= '黄斌';(此时建立了联合索引(user_name,age),索引user_name是有效的,因为满足最左前缀原则,但是age单独是不成索引的,所以建立联合索引的前提要考虑好谁在左,谁在右,可以根据使用频率,占用空间大小)
注:使用联合索引的使用,不用担心where后面条件的顺序是否会影响联合索引的顺序,优化器会自动做优化.
参考资料: