2012-11-27 21 views
0

可能重複:
Does Oracle fetch all the rows before evaluating rownum?Oracle在where子句中應用篩選器之前是否獲取所有行?

如果我運行100K行

在桌子下面的查詢
select * from 
(
select rownum rownumber, fname, lastname 
from customers 
) where rownumber between 1 and 100; 

Oracle是否獲取所有100K然後過濾行列表取得第一個100或者它有一個聰明的方式過濾到前100而不需要獲取所有100k行?

有沒有辦法找出Oracle在上面的例子中是如何實際執行提取的?

+0

執行計劃很可能會告訴你。 – Magnus

+0

如果Oracle不優化這個並獲取100k行,我想要回我的錢。 – user964970

+0

@ user964970,我非常懷疑任何人曾經付過Oracle許可證:-)。 – Ben

回答

3

首先,由於您的內部查詢沒有進行任何排序,您的查詢將返回任意100行。如果這是試圖構建查詢來遍歷結果的頁面,那麼這不是合適的方法,因爲它效率不高,並且因爲它不正確 - 返回的行集可能會隨時間而改變,行可能會很容易出現在結果的許多不同頁面上或根本沒有頁面。

雖然通過查看查詢計劃來查看應用過濾器的時間很簡單。我將建立一個簡單的表FOO有100,000行

SQL> drop table foo; 

Table dropped. 

SQL> create table foo 
    2 as 
    3 select level col1 
    4 from dual 
    5 connect by level <= 100000; 

Table created. 

現在,啓用自動跟蹤,抑制實際數據的顯示和運行查詢

SQL> set autotrace traceonly; 

SQL> select * 
    2 from (select rownum rn, col1 
    3   from foo) 
    4 where rn between 1 and 100; 

100 rows selected. 


Execution Plan 
---------------------------------------------------------- 
Plan hash value: 3193632835 

---------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
---------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  | 101K| 2577K| 47 (3)| 00:00:01 | 
|* 1 | VIEW    |  | 101K| 2577K| 47 (3)| 00:00:01 | 
| 2 | COUNT    |  |  |  |   |   | 
| 3 | TABLE ACCESS FULL| FOO | 101K| 1288K| 47 (3)| 00:00:01 | 
---------------------------------------------------------------------------- 

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

    1 - filter("RN"<=100 AND "RN">=1) 

Note 
----- 
    - dynamic sampling used for this statement (level=2) 


Statistics 
---------------------------------------------------------- 
      0 recursive calls 
      0 db block gets 
     164 consistent gets 
      0 physical reads 
      0 redo size 
     2504 bytes sent via SQL*Net to client 
     590 bytes received via SQL*Net from client 
      8 SQL*Net roundtrips to/from client 
      0 sorts (memory) 
      0 sorts (disk) 
     100 rows processed 

如果你看一下查詢計劃,你可以看到我們在應用rn between 1 and 100謂詞之前完成了FOO的全表掃描。因此,整個結果集已經實現(並且一致性獲取的數量大致是表中的塊數)。

如果你使用一個更合適的分頁查詢(例如,湯姆凱特有一個Oracle Magazine article on pagination和更長的discussion of pagination on askTom),你會看到在查詢計劃就像SORT ORDER BY STOPKEY的東西,告訴你,它知道它可以後停止處理某一點。