PostgreSQL查询优化:查询条件优化一(条件分类)

在SQL中,查询条件在查询优化阶段需要被分成三种类型,三类条件有不同的作用,在某些情况下,可以相互转化。
首先说明一下SQL语句的执行步骤,可以分为三步:一,读取表中的元组;二,如果有JOIN,则开始做JOIN;三,针对WHERE条件作过滤。我们以简单的SQL为例:
表TBL(c1 int, c2 int, c3 int);
有SQL语句 :SELECT A.c1, B.c3 FROM TBL A , TBL B WHERE A.c1 = B.c3 AND A.c2 = 4;
针对上面的SQL语句,执行过程为:一,读取A,B表中的每一条元组;二,将A,B的各个元组作笛卡尔积;三,使用WHERE条件对连接的结果作过滤。
针对上述执行的三个阶段,我们将SQL中的条件也分为三类:
A类,表的过滤条件,对基表读取出来的元组进行过滤;
B类,表的连接条件,两个表作连接,以它为连接条件;
C类,连接的过滤条件,连接完成后,对连接的结果按该条件过滤。
对上述SQL语句而言,它与下面的SQL语句等价:
SELECT A.c1, B.c3 FROM (
SELECT * FROM TBL WHERE A.c2 = 4
) A INNER JOIN TBL B ON (A.c1 = B.c3) WHERE true;
则将原SQL语句的WHERE中的两个条件,一个下推到基表上作为表的过滤条件(A.c2 = 4),另一个下推到两个表,作为它们的连接条件(A.c1 = B.c3)。而此时,连接的过滤条件为WHERE子句上的true,也即没有连接的过滤条件。

在针对表之间的连接为内连接时,WHERE条件上的各个以AND连接的表达式可以随便地下推到基表作基表的过滤条件或者是连接上作连接条件,但当连接不为内连接时,该下推是不正确的, 参看下面的示例:
表TBL_1 (C1 int, c2 int); 有元组(1, 1), (2, 2)
表TBL_2 (c1 int, c2 int); 有元组(1, 1), (null, null)
则此时
SELECT * FROM TBL_1 LEFT JOIN TBL_2 ON true WHRER TBL_1.c1 = TBL_2.c2;
它的查询结果为:(1, 1, 1, 1)
而将WHERE条件下推到连接条件时,即SQL语句为
SELECT * FROM TBL_1 LEFT JOIN TBL_2 ON (TBL_1.c1 = TBL_2.c2) WHRER true;
则它的查询结果为(1, 1, 1, 1), (2, 2, null, null)。
它们结果的不同是由于(TBL_1.c1 = TBL_2.c2)作为连接条件时,代表的意义是:对TBL_1中的一条元组,如果能与TBL_2中的任何一条元组使得(TBL_1.c1 = TBL_2.c2)值为TRUE,则将其连接,返回;如果没有,则将TBL_1的元组输出,右端补空。而当这个条件作为连接的过滤条件时,它会将(2, 2, null, null)过滤掉,因为它不满足该连接的过滤条件。

你可能感兴趣的:(PostGreSQL)