mysql索引机制

常见的索引模型

1、hash

hash表是一个键值对,把值放在数组里。key经过hash函数换算成一个确定的位置。value放在数组的这个位置。

但是多个key,经过hash函数不可避免的会换算成相同值,出现这种情况会拉出一个链表。但是链表不是有序的,区间查询会很慢。

所以hash只适合存放一些等值查询的场景。

2、有序数组

存在数组的普遍特点:查询效率很高,但是更新效率很低,因为中间插入一条数据,为了保证有序,需要移动后面所有的数据。

所以有序数组只适合存储仅查询的静态存储引擎。比如要保存一个城市所有2017年的数据,只需要查询,不需要更新。

3、innoDB引擎的B+树

每一个索引在innoDB引擎中都会维护一个B+树,例如一个表有个主键ID,字段k,并且字段k上存在索引,如下:

主键索引叶子节点存储的是全部数据,称之为聚簇索引。

非主键索引叶子节点存储的是主键ID,称之为二级索引。

一条sql语句:select * from table where id=100;只需要查询主键ID的B+树

select * from table where k=1;则需要查询索引k的B+树,得到对应的主键ID=100,再根据主键ID查询主键ID的B+树,我们称之为回表。

而如果sql语句变为:select id from table where k=1;则查询到索引k的B+树以后,就能得到想得到的ID值,而不需要再去查询主键ID的B+树,可以避免回表。


索引维护

B+ 树为了维护索引有序性,在插入新值的时候需要做必要的维护。以上面这个图为例,如果插入新的行 ID 值为 700,则只需要在 R5 的记录后面插入一个新记录。如果新插入的 ID 值为 400,就相对麻烦了,需要逻辑上挪动后面的数据,空出位置。

而更糟的情况是,如果 R5 所在的数据页已经满了,根据 B+ 树的算法,这时候需要申请一个新的数据页,然后挪动部分数据过去。这个过程称为页分裂。在这种情况下,性能自然会受影响。

为什么普遍要用一个自增字段当主键索引?

因为自增主键的每次插入数据都是追加操作,不存在页分裂。

而且自增主键的占用空间大小也比业务主键小。


最左原则

如下图所示:


select * from table where name like '张%';会走到索引

组合索引(name,age)

索引下推

上面的索引,查询条件:

select * from table where name=张三 and age=10;

会根据name=张三找到ID4,age符合然后进行回表查询,对应的ID5也会进行回表查询数据。而ID6的age不符合条件,则不进行回表,直接过滤掉。

所以此时创建组合索引(name,age)就比只有一个name的索引少了一些数据的回表操作。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容