20-Mysql内核查询优化规则详解
在前面的课程中我们看到当我们把SQL语句交给MySQL执行后,MySQL在执行的过程中会有很多的优化措施,比如索引条件下推,回表中的MRR、索引合并等等。但是在执行之前,MySQL会依据一些规则,竭尽全力的把我们的SQL语句进行转换,以期可以达到成某种可以更高效执行的形式,这个过程也可以被称作查询重写或者查询优化,很多时候这些优化可以由我们自行完成以减少MySQL的优化时间。
条件化简
我们编写的查询语句的搜索条件本质上是一个表达式,这些表达式可能比较繁杂,或者不能高效的执行,MySQL的查询优化器会为我们简化这些表达式。
移除不必要的括号
有时候表达式里有许多无用的括号,比如这样:
((a = 5 AND b = c) OR ((a > c) AND (c < 5)))
优化器会把那些用不到的括号给干掉,就是这样:
(a = 5 and b = c) OR (a > c AND c < 5)
常量传递(constant_propagation)
有时候某个表达式是某个列和某个常量做等值匹配,比如这样:
a = 5
当这个表达式和其他涉及列a的表达式使用AND连接起来时,可以将其他表达式中的a的值
替换为5,比如这样:
a = 5 AND b > a
就可以被转换为:
a = 5 AND b > 5
等值传递(equality_propagation)
有时候多个列之间存在等值匹配的关系,比如这样:
a = b and b = c and c = 5
这个表达式可以被简化为:
a = 5 and b = 5 and c = 5
移除没用的条件(trivial_condition_removal)
对于一些明显永远为TRUE或者FALSE的表达式,优化器会移除掉它们,比如这个表达式:
(a < 1 and b = b) OR (a = 6 OR 5 != 5)
很明显,b = b这个表达式永远为TRUE,5 != 5这个表达式永远为FALSE,所以简化后的表达式就是这样的:
(a < 1 and TRUE) OR (a = 6 OR FALSE)
可以继续被简化为
a < 1 OR a = 6
表达式计算
在查询开始执行之前,如果表达式中只包含常量的话,它的值会被先计算出来,比如这个:
a = 5 + 1
因为5 + 1这个表达式只包含常量,所以就会被化简成:
a = 6
但是这里需要注意的是,如果某个列并不是以单独的形式作为表达式的操作数时,比如出现在函数中,出现在某个更复杂表达式中,就像这样:
ABS(a) > 5
或者:
-a < -8
优化器是不会尝试对这些表达式进行化简的。我们前边说过只有搜索条件中索引列和常数使用某些运算符连接起来才可能使用到索引,所以如果可以的话,最好让索引列以单独的形式出现在表达式中。