相關子查詢優化

轉自;http://tech.it168.com/a2011/0927/1252/000001252751.shtml

 

IT168 專稿】隨着信息化的普及,信息系統覆蓋到各行各業,根據實際業務需求,對數據庫的查詢方式越來越複雜。子查詢在複雜查詢中的使用率較高,其性能直接影響到業務處理效率,因此,優化子查詢對於DBA和開發人員是需要掌握的一項技術。如果數據庫內部可以對子查詢進行優化處理,則一方面大大減少了技術人員的工作量,另一方面也簡化了SQL語句的複雜度。DM7對子查詢進行了大量優化處理,提升了子查詢的性能。下面以DM7在相關子查詢的優化爲例進行闡述。

  概述

  本文中對子查詢的描述使用術語內表和外表。子查詢內出現的表稱之爲內表;只在子查詢之外出現的表稱之爲外表。

  子查詢包括相關子查詢和非相關子查詢。

  (1)相關子查詢

  子查詢中的過濾條件存在外表列和內表列的連接,會影響最終的查詢結果。

  例1:

    createtable t1(c1int,c2int);

  
createtable t2(d1int,d2int);

  
select*from t1where c1in(select d1from t2where c2=d2);

 

 例1中的子查詢中條件爲c2=d2,條件列分別屬於t1和t2表。查詢結果不僅要滿足c1=d1,還要滿足c2=d2。

  (2)非相關子查詢

  子查詢不包含外表的列,查詢結果由內表決定。

  例2:

 

create table t1(c1int,c2int);

  
createtable t2(d1int,d2int);

  
select*from t1where c1in(select d1from t2where c2<10);

 

例2中的子查詢條件爲c2<10,最終結果需要滿足條件c1=d1 and c2<10,查詢結果不受t1表影響。

  優化

  1、優化前的處理方式

  以外表驅動,從外表每取一條記錄,遍歷一遍內表,按照過濾條件判斷

  是否滿足,如果滿足則輸出,否則不處理。相當於內表和外表做了一次笛卡爾集,在大數據量情況下,執行效率非常低。

  例如,兩張60萬的數據表執行子查詢,笛卡爾集會產生3600億條記錄,對這3600億條記錄進行過濾,計算量和IO量都是巨大的,執行時間是無法被用戶接受的。

  對於例1的查詢語句,執行過程如圖1所示。

達夢數據庫:DM7相關子查詢優化
▲圖1 相關子查詢優化前執行流程

  2、優化後的處理方式

  對於相關子查詢的優化思想是轉換爲半連接進行處理,執行過程爲:

  (1) 讀取外表的一批數據;

  (2) 把滿足連接條件的記錄打上標記;

  (3) 處理完本批數據,返回有標記(in/exists)或無標記(not in/not exists)的記錄;

  (4) 循環處理步驟1到步驟3,直到外表數據處理完。

  把相關子查詢中與內表關聯的外表下放到子查詢中,與內表進行連接,連接的結果包括外表的rowid,最後以rowid爲連接條件與外表進行連接,根據規則進行優化處理,轉換爲半連接的方式,我們稱這個過程爲去相關性。

 

1. 非反半連接

  非反半相關子查詢的算法如下:、

 

 

算法

  FOR EACH row1 IN outer table LOOP

  
FOR EACH row2 IN inner table LOOP

  
IF jc(row1, row2) == TRUE && ic(row1, row2) == TRUE THEN

  row1 can
return;

  
END IF;

  
END LOOP

  
END LOOP

 

算法中jc表示連接條件;ic表示in過濾條件。

  從上述算法可以看出,只有同時滿足jc和ic的情況下,記錄纔會被輸出。因此,從算法中得出相關子查詢可以轉換爲連接查詢,連接條件爲jc and ic。下面舉例說明。

  例3:

 

     create table t1(c1 int, c2 int);

  
create table t2(d1 int, d2 int);

  
select c1,c2 from t1 where c1 in(select d1 from t2 where c2=d2);

對例3的去相關性優化過程分三步進行。

  第一步:下放與子查詢相關的外表到子查詢中進行連接

  子查詢語句轉換爲:

select t1.rowid, d1 from t2 ,t1 where c2=d2;

執行過程如圖2所示:

達夢數據庫:DM7相關子查詢優化
▲圖2 下放外表執行過程圖

  第二步:子查詢與外表以t1.rowid爲條件進行半連接

  原始查詢改寫爲:select c1,c2 from t1 a,(select t1.rowid, d1 from t2 ,t1 where c2=d2) b where a.rowid=b.rowid and a.c1=b.d1;

  執行過程如圖3所示:

達夢數據庫:DM7相關子查詢優化

▲圖3 子查詢與外表半連接過程圖

  第三步:對於滿足條件的半連接進行規則優化,條件如下:

  a. 連接類型爲半連接;

  b. 父親節點右孩子爲cross join,其中cross join的左孩子存在於根節點左孩子列表中,則cross join節點的左孩子替換爲根節點的左孩子,同時cross join變爲semi join。

  最終的執行過程如圖4所示:

達夢數據庫:DM7相關子查詢優化
▲圖4 半連接優化過程圖

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