背景
最近频繁呈现慢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