oracle execution order and function calculations

时间:2015-10-08 08:48:09

标签: sql oracle rownum

Lets say we have a table which has 6million records.

CREATE TABLE MYTABLE
(
  KEY1 NUMBER(15),
  ANALYSENO    NUMBER(15),
  ADDRESSNO    NUMBER(15),
  ABC          NUMBER(3),
  ABCDETAIL    CLOB
)

AND i have two queries.

first one:

 Select m.*,
        CASE WHEN dbms_lob.INSTR(m.ABCDETAIL,'ABC$$') = 0 THEN '' ELSE
        dbms_lob.SUBSTR(m.ABCDETAIL,dbms_lob.INSTR(m.ABCDETAIL,'##AAA')-dbms_lob.INSTR(m.ABCDETAIL,'ABC$$')-10,dbms_lob.INSTR(m.ABCDETAIL,'ABC')+10) END) as SOMECALC 
 from MYTABLE m 
 where m.ABC = 1 
       and ROWNUM < 1000
       and CASE WHEN dbms_lob.INSTR(m.ABCDETAIL,'ABC$$') = 0 THEN '' ELSE
        dbms_lob.SUBSTR(m.ABCDETAIL,dbms_lob.INSTR(m.ABCDETAIL,'##AAA')-dbms_lob.INSTR(m.ABCDETAIL,'ABC$$')-10,dbms_lob.INSTR(m.ABCDETAIL,'ABC')+10) END like '%AAA%';

second one:

Select a.* from
    (Select m.*,
        CASE WHEN dbms_lob.INSTR(m.ABCDETAIL,'ABC$$') = 0 THEN '' ELSE
        dbms_lob.SUBSTR(m.ABCDETAIL,dbms_lob.INSTR(m.ABCDETAIL,'##AAA')-dbms_lob.INSTR(m.ABCDETAIL,'ABC$$')-10,dbms_lob.INSTR(m.ABCDETAIL,'ABC')+10) END as SOMECALC 
     from MYTABLE m 
     where m.ABC = 1 
           and ROWNUM < 1000) a 
     where a.SOMECALC like '%AAA%';

The only difference is that in second query calculation functions are not used on where statement. And be careful i m using ROWNUM < 1000 statement for where query.

So the questions are the following

1- is there any difference between two queries?

2- can we say that ROWNUM < 1000 statement calculated lastly in all statement execution?

3- using some functions (length, case when, instr etc) lazy evaluted?

2 个答案:

答案 0 :(得分:1)

是的,两个查询之间存在差异。

在第一个查询中,您要说的是获取与所有其他过滤条件匹配的前999行。

在第二个查询中,您说要获取m.abc = 1的前999行,然后过滤那些somecalc字段为'%AAA%'的行。

最终,第二个查询显示的行数可能会减少。如果您将log4js谓词移动到第二个查询的外部查询,那么您将拥有与第一个查询相同的查询。

答案 1 :(得分:0)

首先,两个查询都有语法错误。 CASE表达式中有一个额外的右括号。

无论如何,回到你原来的问题:

  

1-两个查询之间有什么区别吗?

  

我们可以说ROWNUM&lt;最后在所有语句执行中计算的1000语句?

没有

区别在于过滤谓词。要理解它,请比较解释计划

查询1

SQL> set autot on explain
SQL> SELECT m.*,
  2    CASE
  3      WHEN dbms_lob.INSTR(m.ABCDETAIL,'ABC$$') = 0
  4      THEN ''
  5      ELSE dbms_lob.SUBSTR(m.ABCDETAIL,dbms_lob.INSTR(m.ABCDETAIL,'##AAA')-
  6      dbms_lob.INSTR(m.ABCDETAIL,'ABC$$')-10,dbms_lob.INSTR(m.ABCDETAIL,'ABC')+10)
  7    END AS SOMECALC
  8  FROM MYTABLE m
  9  WHERE m.ABC = 1
 10  AND ROWNUM  < 1000
 11  AND
 12    CASE
 13      WHEN dbms_lob.INSTR(m.ABCDETAIL,'ABC$$') = 0
 14      THEN ''
 15      ELSE dbms_lob.SUBSTR(m.ABCDETAIL,dbms_lob.INSTR(m.ABCDETAIL,'##AAA')-
 16      dbms_lob.INSTR(m.ABCDETAIL,'ABC$$')-10,dbms_lob.INSTR(m.ABCDETAIL,'ABC')+10)
 17    END LIKE '%AAA%';

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 1231656364

------------------------------------------------------------------------------
| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |         |     1 |  2054 |     2   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY     |         |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| MYTABLE |     1 |  2054 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(ROWNUM<1000)
   2 - filter("M"."ABC"=1 AND CASE "DBMS_LOB"."INSTR"("M"."ABCDETAIL",'A
              BC$$') WHEN 0 THEN '' ELSE "DBMS_LOB"."SUBSTR"("M"."ABCDETAIL","DBMS_LOB
              "."INSTR"("M"."ABCDETAIL",'##AAA')-"DBMS_LOB"."INSTR"("M"."ABCDETAIL",'A
              BC$$')-10,"DBMS_LOB"."INSTR"("M"."ABCDETAIL",'ABC')+10) END  LIKE
              '%AAA%')

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

查询2

SQL> SELECT a.*
  2  FROM
  3    (SELECT m.*,
  4      CASE
  5        WHEN dbms_lob.INSTR(m.ABCDETAIL,'ABC$$') = 0
  6        THEN ''
  7        ELSE dbms_lob.SUBSTR(m.ABCDETAIL,dbms_lob.INSTR(m.ABCDETAIL,'##AAA')-
  8        dbms_lob.INSTR(m.ABCDETAIL,'ABC$$')-10,
  9        dbms_lob.INSTR(m.ABCDETAIL,'ABC')+10)
 10      END AS SOMECALC
 11    FROM MYTABLE m
 12    WHERE m.ABC = 1
 13    AND ROWNUM  < 1000
 14    ) a
 15  WHERE a.SOMECALC LIKE '%AAA%';

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 76631248

-------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |         |     1 |  4056 |     2   (0)| 00:00:01 |
|*  1 |  VIEW               |         |     1 |  4056 |     2   (0)| 00:00:01 |
|*  2 |   COUNT STOPKEY     |         |       |       |            |          |
|*  3 |    TABLE ACCESS FULL| MYTABLE |     1 |  2054 |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("A"."SOMECALC" LIKE '%AAA%' AND "A"."SOMECALC" IS NOT
              NULL)
   2 - filter(ROWNUM<1000)
   3 - filter("M"."ABC"=1)

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

您在解释计划中看到 COUNT STOPKEY ,这是因为 ROWNUM 用于过滤行。因此,在第一个解释计划中,首先应用STOPKEY,然后在第二个查询中应用filter("A"."SOMECALC" LIKE '%AAA%' AND "A"."SOMECALC" IS NOT NULL).