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)過濾掉,因爲它不滿足該連接的過濾條件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章