2012-07-19 140 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。我的建议是使用括号以避免混淆。