条件化简

一、 什么是查询条件

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”表达式的优化。

撰写日期 March 1, 2018