有MySQL使用经验的同学在实际项目中可能会遇到SQL慢查询的场景,有些场景很容易定位问题所在(如单表操作有慢查询SQL时,仔细check SQL语句通常很容易定位索引问题),而有些复杂业务场景下(如多表联合查询几十个字段并做group或sort等操作),人工check SQL语句通常很难发现SQL瓶颈根源。这个时候,MySQL提供的explain命令就派上用场了。
本笔记主要对explain的输出结果做说明,并给出根据explain输出对SQL做优化的思路。
1. EXPLAIN语法及用途explain命令的语法说明见官网文档,这里略过。
该命令主要作用是输出MySQL的optimizer对SQL的执行计划,也即,MySQL会解释如何处理输入的SQL(是否使用索引,使用 哪个索引,多表以什么顺序及什么关联字段做join)。
explain的提示可以帮助大家意识到哪些字段应该建索引,也可以帮大家确认SQL执行时optimizer是否会以合理的顺序来 join多张表。比如若有类似这样的SQL语句:
select t1.id, t2.link, t3.detail from t1, t2, t3 where t1.id < 100 and t1.id = t2.base_id and t3.link_sign = t2.sign;
该语句执行时,optimizer不一定会以from列出的表顺序来join这3张表,而表的join顺序很可能会影响SQL性能。
这种场景下,如果想让optimizer以from语句列出的表顺序做join,有2种方法:
1) 在select关键字后添加STRAIGHT_JOIN来提示optimizer按from列出的表顺序来join,具体语法见SELECT文档
2) 调整sql where条件中各表关联字段在等号前后的位置
本文下面的内容会说明如何通过explain输出来确定多表join时optimizer对各表的执行次序,以及如何调整SQL来影响optimizer的执行计划。
2. EXPLAIN输出格式说明explain命令会为SQL中出现的每张表返回一行信息来说明optimizer将会如何操作这张表,其输出中列出的表次序也是MySQL实际执行SQL时对各表的处理顺序。
MySQL以nested-loop算法处理所有的join操作,算法原理说明在这里,对认识join的行