mysql 为什么总是推荐使用联合索引而不是单值索引

mysql 为什么总是推荐使用联合索引而不是单值索引,第1张

有一句话是有谬误的: 在where条件中使用到的字段都加上索引。这个结论似乎成为了好多人的习惯性结论。

事实上我们只需要添加一个联合索引包括这些字段,而不是为每个字段分别添加索引! 这不仅仅是对空间的浪费,而且真正起作用的只是其中一个!

可以做出实验在验证下:

tb_box 表有100万条数据

查询语句如下:

1、先为tb_box的sb_number、create_time字段分别建立a、b索引

执行计划如下,key的值为a 表示只是使用到a索引,b索引未使用!而且extra中出现了using where,表明有字段参与where而不是索引直接参与where

执行时间 0.442秒

2、重新建立索引,为tb_box添加一个联合索引包含sb_number、create_time字段

查看执行计划,a索引被直接使用。索引长度是137比单独创建的131大,说明有更多索引生效。rows=76969比80910小,表明扫描更少的行就能找到结果了

执行时间 0.181秒,快了接近4倍

建立索引的时候,尽量建立联合索引,即多个字段组成1个索引。因为如果针对单个字段建立索引的话,会造成索引过多,每次插入数据都会维护多个索引,导致数据加入性能过慢。索引条目里面一定会带一个id,区分大小的唯一主键。

聚合索引就是根据多个字段建立起来的索引,索引树的最底层的数据页保存的是索引字段+主键字段。如果字段值一样的话,就按照下一个字段排序。例如,建立一个persion表, 有字段 id,name, age , height ,weight,phone 。

然后用age ,height 建立联合索引,如下图:

这时候,添加一个age=18,height=177的用户的添加过程是去到索引页1,发现age >15并且age <20 ,所以这条记录会添加到数据页1。 然后去数据页1根据age进行二分查找,发现age>最后一条数据(id=4),这时候就将需要添加的数据,加到最后一条后面。

如果再添加一条数据age=21 ,height=167。 首先去到索引页1用age进行二分查找,发现应该添加到数据页2。然后去数据页2进行二分查找,发现age=21和id=6,id=7的数据age一样。 然后就看第二个字段height=167,比id=6的166大,比id=7的170小,所以就添加到id=6 和 id=7的数据中间。

如果遇到字段都一样的,就根据ID的大小来排序。

在where子句里面的字段,条件都是用“=”等号,字段和也索引里面的字段一致,顺序不一致也没关系,SQL优化会自动进行重新排序。这时候就可以100%使用索引进行查询。

例如上面的例子,如果查询的时候,是使用age = xx 查询,那么就可以用上索引。如果跳过age,使用height=XX来查询,那么是没办法使用到索引的,因为索引的排序是根据建立索引的字段顺序来排序的。

查询的时候,如果使用了like类型的模糊匹配, like%,这样的写法是可以用索引的,当然要符合最左列匹配规则。 如果是%like 这样的写法,是无法使用索引的,因为无法确认字段的开始字符串是什么,所以就无法用来和索引进行对比。

如果使用了范围查找,使用索引的最左列字段来查找是可以使用索引查找的。因为索引的每一层和数据页都是通过双向量表连接起来的。 例如age >15 and age <21,那么就可以定位到数据页1,id=1的数据和数据页2,id=5的数据,然后取个范围内的数据就可以了。

但是如果用的是height来做范围查找就用不了索引: height >170 and height <180。 这时候数据页1 和数据页2 都是存在符合条件的数据的,但是,数据页内,没有按照height来排序,所以,需要遍历才能找到,然后数据页2也需要遍历才能找到。

第一个条件是使用了=来匹配,如果这个条件的字段是索引的第一个字段,那么是会走索引的, 然后第二个条件,如果是按照范围来查找, 如果这个字段是索引的第二个字段,那么也可以用到索引, 再来第三个条件, 如果是=号匹配,这个条件也是索引的第三个字段的话,就可以用索引,如果是用范围匹配, 那么是用不了索引的。 原因是,索引用第二个字段进行了排序, 然后第三个字段是在第二个字段相同的情况下,再进行排序。

记住一个原则就是, 索引有3个字段, 先用第一个字段进行排序, 如果第一个字段一样,就用第二个字段排序, 如果第二个字段的值也一样, 那么就用第三个字段排序。 根据这个排序的规则,去匹配查询的条件,即可知道这5个索引的匹配规则。

排序的时候也符合索引使用规则, 使用索引的字段进行排序的话,就可以直接从索引里面,直接获取数据即可。 用上面的例子,如果有SQL :

本身索引就是按照age和height来排序的,所以直接可以在索引里面找到对应的数据,然后取前面2条返回。 升序和降序都没关系,都可以找到一个连续确定的范围。索引默认是从小到大排序。

如果排序是order by age desc height asc,那就不会使用到索引,因为索引也是按照从小到大排序的,遇到第一个字段相同值的,就按照第二个字段从小到大排序。

使用grouop by的时候,也是注意使用索引最左列来分组, 这样,就可以按照顺序,重一定的范围内提取出整个分组数据,然后再对这个分组数据进行 *** 作。 就不需要从无序的数据里面,重新进行排序再提取,这样就会涉及到很多硬盘交互 *** 作。

索引就相当于对指定的列进行排序,排序有利于对该列的查询,可以大大增加查询效率,

建立索引也是要消耗系统资源,所以索引会降低写 *** 作的效率 

主键,唯一,联合都属于索引

主键属于唯一索引,且一个表只能有一个主键,主键列不允许空值唯一索引可以一个表中可以有多个,而且允许为空,列中的值唯一 多个字段的多条件查询多使用联合索引。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9917897.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-03
下一篇 2023-05-03

发表评论

登录后才能评论

评论列表(0条)

保存