背景

最近频繁呈现慢SQL导致系统性能问题,于是决定针对索引进行一些优化。一些表构造自身曾经有了不少索引,如果再持续增加索引,势必会影响到插入数据的性能。那么,是否能够应用组合索引来达到目标呢?这篇文章咱们来一探到底。

意识复合索引

如果where条件中应用到多个字段,并且须要对多个字段建设索引,此时就能够思考采纳复合索引(组合索引)。比方查问地址时须要输出省、市,那么在省、市上建设索引,当数据量大时会明显提高查问速度。

组合索引有啥劣势呢?

  • 缩小查问开销:建设复合索引(c1,c2,c3),实际上相当于建设了(c1),(c1,c2),(c1,c2,c3)三个索引。对于大表来说,能够极大缩小开销。
  • 笼罩索引:MySQL能够间接通过遍历索引获得数据,而无需回表,缩小了很多的随机io操作。
  • 效率高:索引列越多,通过索引筛选进去的数据就越少,从而晋升查问效率。

毛病:

  • 索引字段越多,创立的索引越多,每个索引都会减少磁盘空间的开销;
  • 索引越多对查问效率晋升越高,但对须要更新索引的增删改操作会有效率影响;

复合索引应用倡议:单表最好不要超过1个复合索引,单个复合索引最好不超过3个字段。一旦超过,就须要思考必要性和是否有其余代替计划。

最左匹配准则

复合索引听从最左匹配准则,顾名思义,在组合索引中,最左侧的字段优先匹配。因而,在创立组合索引时,where子句中应用最频繁的字段放在组合索引的最左侧。

辅助索引是B+树实现的,尽管能够指定多个列,然而每个列的比拟优先级不一样,写在后面的优先比拟高。一旦呈现脱漏,在B+树上就无奈持续搜寻了(通过补齐等措施解决的除外),因而是依照最左间断匹配来的。既然是在B+树上搜寻,对于条件的比拟天然是要求准确匹配(即"="和"IN")。

在where子句中用到两个字段c1和c2,那么创立索引时,两个字段的程序应该是(c1,c2)还是(c2,c1)呢?

正确的做法是:把反复值起码的放后面。比方,95%的值都不反复,则可思考放最后面。

字段程序的影响

复合索引听从最左匹配准则,那么在where查问条件中的字段是否也须要依照索引的程序来写呢?

比方,复合索引为(c1,c2,c3),上面两个查问条件是否会对索引有影响呢?

select * from t_user where c1 = 1 and c2 = 4;select * from t_user where c2 = 4 and c1 = 1;

看到有文章提出第一条SQL语句的效率更高,是否可信?两种查问形式条件一样,后果也应该一样,失常来说Mysql也会让它们走同样的索引。

通过Mysql的查问优化器explain剖析上述两个条语句,会发现执行打算完全相同。也就是说:SQL语句中的字段程序并不需要与复合索引字段程序统一,查问优化器会主动调整程序

如果说有效率影响,那么也就是查问优化器改正程序的影响吧,简直能够忽略不计。

单字段是否能够触发索引?

对于复合索引为(c1,c2,c3),相当于(c1),(c1,c2),(c1,c2,c3)三个索引,如果查问条件中只有c1,很显然是会走索引的。

但如果where条件如下呢:

from t_user where c2 = 4;

上述语句是否会走索引呢?这得分几种状况来阐明。

执行explan查问c1为条件的SQL语句:

explain select * from t_user where c1 = 1;

上述语句走的索引类型为:ref。ref类型示意Mysql会依据特定的算法疾速查找到符合条件的索引,而不会对索引中每一个数据都进行扫描判断。这种类型的索引为了疾速查出数据,索引就须要满足肯定的数据结构。

执行explan查问c2为条件的SQL语句:

explain select c2 from t_user where c2 = 4;

上述语句走的索引类型为:index。index类型示意Mysql会对整个索引进行扫描,只有是索引或索引的一部分Mysql就可能会采纳index方类型的形式扫描。因为此种形式是一条数据一条数据查找,性能并不高。

在这个例子中,对查问的字段有肯定的要求,where中条件为c2,select中查问出的字段也只能是c2,才会走index类型的索引

如果将c2换成*或其余字段:

explain select * from t_user where c2 = 4;

上述语句会发现,不再走index索引,而是走全表扫描了。这也从侧面阐明了Mysql为什么要讲最左匹配准则了。

所以论断是:如果单个字段为复合索引的首个字段,则会失常走索引;如果单个字段是复合索引的其余字段,且仅有该字段呈现在select前面,则会走index类型索引;而其余状况,则走全表扫描

复合索引能够代替繁多索引吗?

繁多索引:(c1),复合索引:(c1,c2)。

当c1作为查问条件时,繁多索引和复合索引查问速度简直一样,甚至比复合索引还要略快。

如果仅用复合汇集索引的非起始列(c2)作为查问条件的话,复合索引是不起任何作用的。

对于一张表来说,如果有复合索引(c1,c2),则无需再建繁多索引(c1)。

如果曾经存在繁多索引(c1),因查问所需,可增加复合索引(c1,c2)来晋升效率。

小结

本篇文章整顿了Mysql复合索引应用时所需注意的一些知识点,在应用时能够通过explain来查看一下你的SQL语句是否走了索引,走了什么索引。

但还要理解的是:Mysql的执行打算和查问的理论执行过程并不齐全吻合。

别问我为什么晓得,因为在实践中遇到过。同一条SQL语句,查问条件不同,有可能会走索引,也有可能不会走索引。

博主简介:《SpringBoot技术底细》技术图书作者,热爱钻研技术,写技术干货文章。

公众号:「程序新视界」,博主的公众号,欢送关注~

技术交换:请分割博主微信号:zhuan2quan