2012-07-19 36 views
1

我有以下查詢:類似的查詢有這樣不同的執行時間

SELECT nvl(sum(adjust1),0) 
FROM (
    SELECT 
    ManyOperationsOnFieldX adjust1, 
    a, b, c, d, e 
    FROM (
    SELECT 
     a, b, c, d, e, 
     SubStr(balance, INSTR(balance, '[&&2~', 1, 1)) X 
    FROM 
     table 
    WHERE 
     a >= To_Date('&&1','YYYYMMDD') 
     AND a < To_Date('&&1','YYYYMMDD')+1 
) 
) 
WHERE 
    b LIKE ... 
    AND e IS NULL 
    AND adjust1>0 
    AND (b NOT IN ('...','...','...')) 
    OR (b = '... AND c <> NULL) 

我試圖把它改成這樣:

SELECT nvl(sum(adjust1),0) 
FROM (
    SELECT 
    ManyOperationsOnFieldX adjust1 
    FROM (
    SELECT 
     SubStr(balance, INSTR(balance, '[&&2~', 1, 1)) X 
    FROM 
     table 
    WHERE 
     a >= To_Date('&&1','YYYYMMDD') 
     AND a < To_Date('&&1','YYYYMMDD')+1 
     AND b LIKE '..' 
     AND e IS NULL 
     AND (b NOT IN ('..','..','..')) 
     OR (b='..' AND c <> NULL) 
) 
) 
WHERE 
    adjust1>0 

米的意圖是在最內層查詢所有過濾,並且只給外面的那個我必須經營很多的領域X.然而,firts(原始)查詢需要幾秒鐘才能執行,而第二個查詢甚至不會完成。我等了將近20分鐘,仍然沒有得到答案。

是否有明顯的原因會發生這種情況,我可能會忽略?

這些是他們每個人的計劃:

SELECT STATEMENT optimizer=all_rows (cost = 973 Card = 1 bytes = 288) 
    SORT (aggregate) 
    PARTITION RANGE (single) (cost=973 Card = 3 bytes = 864) 
     TABLE ACCESS (full) OF "table" #3 TABLE Optimizer = analyzed(cost=973 Card = 3 bytes=564) 


SELECT STATEMENT optimizer=all_rows (cost = 750.354 Card = 1 bytes = 288) 
    SORT (aggregate) 
    PARTITION RANGE (ALL) (cost=759.354 Cart = 64.339 bytes = 18.529.632) 
     TABLE ACCESS (full) OF "table" #3 TABLE Optimizer = analyzed(cost=750.354 Card = 64.339 bytes=18.529.632) 
+1

每個查詢的解釋計劃是什麼? – Ollie 2012-07-19 14:51:42

+0

第二個SQL中有一個語法錯誤 - adjust1(第一個SQL在第二個SQL中缺少的下一行上有一個列表「a,b,...」)後的逗號逗號。 – 2012-07-19 14:53:02

+3

該計劃顯示您的第二個查詢正在掃描您桌面上的所有分區,而第一個只掃描一個分區,因此速度更快。看看兩次掃描之間的成本差異。 – Ollie 2012-07-19 15:00:11

回答

2

這就是你的或者......試試這個:

SELECT nvl(sum(adjust1),0) 
FROM (
    SELECT 
    ManyOperationsOnFieldX adjust1 
    FROM (
    SELECT 
     SubStr(balance, INSTR(balance, '[&&2~', 1, 1)) X 
    FROM 
     table 
    WHERE 
     a >= To_Date('&&1','YYYYMMDD') 
     AND a < To_Date('&&1','YYYYMMDD')+1 
     AND (
      b LIKE '..' 
      AND e IS NULL 
      AND (b NOT IN ('..','..','..')) 
      OR (b='..' AND c <> NULL) 
    ) 
) 
) 
WHERE 
    adjust1>0 

因爲你有或內聯同其餘的AND語句沒有括號,第二個版本不會將檢查的數據限制爲日期過濾器中的行。欲瞭解更多信息,請參閱文檔Condition Precedence

+0

就是這樣。謝謝!! – Alex 2012-07-19 15:15:49

3

您的兩個查詢不相同。

logical operator AND is evaluated before the operator OR

SQL> WITH data AS 
    2   (SELECT rownum id 
    3    FROM dual 
    4   CONNECT BY level <= 10) 
    5 SELECT * 
    6 FROM data 
    7 WHERE id = 2 
    8  AND id = 3 
    9  OR id = 5; 

     ID 
---------- 
     5 

所以你的第一個查詢是指:給我很大的SUM在這個分區時的數據是這樣。

你的第二個查詢的意思是:給我很大的SUM過(當數據是這樣該分區)或(當數據是這樣的其他方式[無分區消除,因此大的全掃描])

要小心當混合邏輯運算符ANDOR。我的建議是使用括號以避免混淆。