条件化简
一、 什么是查询条件
1、什么是条件?
SQL查询语句中,对元组进行过滤和连接的表达式。形式上是出现在WHERE/JOIN-ON/HAVING的子句中的表达式。
SELECT …
[WHERE where_condition]
[HAVING where_condition]
join_condition:
ON conditional_expr
从官方给出的解释是:一般来说,就是使用了ON子句和使用WHERE子句来限制结果集中想要的行的结果。
一般来说,条件优化的技术可以是条件下推,把与单个表相关的条件,放到对单表进行扫描的过程中执行。例如:
SELECT *
FROM A, B
WHERE A.a=1 and A.b=B.b;
执行顺序:
1)扫描A表,并带有条件A.a=1,把A表作为嵌套循环的外表;
2)扫描B表,执行连接操作,并带有过滤条件A.b=B.b;
说明:
数据库系统都支持条件下推,且无论条件对应的列对象有无索引
系统自动进行优化,不用人工介入
二、什么是条件化简技术
条件化简是条件优化的另外一项技术,主要包括:
1)1WHERE、HAVING和JOIN-ON条件由许多表达式组成,而这些表达式在某些时候彼此之间存在一定的联系;
2)利用等式和不等式的性质,可以将WHERE、HAVING和ON条件化简;
3)但不同数据库的实现可能不完全相同。
1、把HAVING条件并入WHERE条件
优点:
便于统一、集中化解条件子句,节约多次化解时间。
注意:
不是任何情况下HAVING条件都可以并入WHERE条件,只有在SQL语句中不存在GROUPBY条件或聚集函数的情况下,才能将HAVING条件与WHERE条件的进行合并。
DB> select * from t3 where a3>1 having b3=3;
优化后:select * from t3 where a3>1 and b3=3;
2、去除表达式中冗余的括号
优点:
可以减少语法分析时产生的AND和OR树的层次。—减少CPU的消耗
示例: ((a AND b)AND (c AND d))
化简为:
a AND b AND c AND d
3、常量传递
优点:
对不同关系可以使得条件分离后有效实施“选择下推”,从而可以极大减小中间关系的规模。
例如:
col_1 = col_2 AND col_2 = 3
转化为 [col_1, col_2, 3], 所以可以推知: col_1=3 AND col_2=3。
注意:
操作符“=、<、>、<=、>=、<>、<=>、LIKE”中的任何一个,在“col_1 <操作符> col_2”条件中都可能会发生常量传递操作符>
4、消除死码
化简条件,将不必要的条件去除。
示例:
WHERE(0 > 1 AND s1 = 5),
“0 > 1”使得AND恒为假,则WHERE条件恒为假。
此时就不必要再对该SQL语句进行优化和执行了,加快了查询执行的速度。
5、表达式计算
对可以求解的表达式,进行计算,得出结果。
示例:
WHERE col_1 = 1 + 2
变换为:
WHERE col_1 = 3
6、等式变换
化简条件(如反转关系操作符的操作数的顺序),从而改变某些表的访问路径
示例:
-a = 3
可化简为
a = -3
这样的好处是如果a上有索引,则可以利用索引扫描来加快访问。
7、不等式变换
化简条件,将不必要的重复条件去除。
示例:
a > 10 AND b = 6 AND a > 2
可化简为
b = 6 AND a > 10
8、布尔表达式变换
1)谓词传递闭包
一些比较操作符,如“<”、“>”等,具有传递性,可以起到化简表达式的作用
示例:
a>b AND b>2
可以推导出a>b AND b>2 AND a>2,“a>2”是一个隐含条件,这样把“a>2”和“b>2”分别下推到对应的关系上,就可以减少参与比较操作“a>b”的元组了。
2)布尔表达式被转换为一个等价的合取范式(CNF)
任何一个布尔表达式都能被转换为一个等价的合取范式(CNF)
合取范式格式为:C1 AND C2 AND… AND Cn;其中,Ck(1<=k<=n)称为合取项,每个合取项是不包含AND的布尔表达式
说明:
(1)合取项只要有一个为假,整个表达式就为假,故代码中可以在发现一个合取项为假时,即停止其他合取项的判断,加快判断速度;
WHERE(0 > 1 AND s1 = 5)
(2)另外因为AND操作符是可交换的,所以优化器可以按照先易后难的顺序计算表达式,一旦发现一个合取项为假时,即停止其他合取项的判断,加快判断速度。 WHERE(A.a+B.b > 100 AND A.b = 5 AND 0 > 1 )
先求解:0 > 1 ,值为假,其他不再求解
3)索引利用
如果一个合取项上存在索引,则先判断索引是否可用,如能利用索引快速得出合取项的值,则能加快判断速度。同理,OR表达式中的子项也可以利用索引。 示例:
WHERE (A.a> 100 AND A.b = 5 AND… )
情况1:A表的a列上存在索引,b列无索引,则利用a上的索引找出元组,“A.b = 5” 作为过滤条件使用。
情况2:A表的a列上不存在索引,b列有索引,则利用b上的索引找出元组,“A.a> 100” 作为过滤条件使用。
三、MySQL支持的条件化简技术有哪些?(基于MySQL5.6x)
(一)把HAVING条件并入WHERE条件:不支持
在MySQL5.6源码中,该部分有一个宏代码,可能在某些版本中支持,但是在实际的使用时候,这个部分的代码被注释掉了,所以根本上来说是不支持的。
(二)去除表达式中冗余的括号:支持
(三)常量传递:支持
(四)消除死码:支持
(五)表达式计算:支持
(六)等式变换:不支持
(七)不等式变换:不支持
(八)布尔表达式变换—谓词传递闭包:不支持
(八)布尔表达式变换—布尔表达式被转换为等价的合取范式:支持
(八)布尔表达式变换—索引的利用—AND操作符是可交换的:支持 代码中,MySQL支持对条件按表连接的次序进行排序,优先判断连接的表涉及的条件。
(九)IS NULL表达式优化:支持 利用索引,支持“IS NULL”表达式的优化。