可能重复:
Does Oracle fetch all the rows before evaluating rownum?
如果我在具有100k行的表上运行以下查询
select * from
(
select rownum rownumber, fname, lastname
from customers
) where rownumber between 1 and 100;
Oracle是否获取所有100k,然后过滤获取的行列表以获得前100个,或者它是否有一种巧妙的过滤方式,前100个而不是获取所有100k行?
有没有办法在上面的例子中找出Oracle实际上如何进行提取?
答案 0 :(得分:3)
首先,由于您的内部查询没有进行任何排序,因此查询返回任意100行。如果这是尝试构建查询以遍历结果,那么这不是正确的方法,因为它不高效且因为它不正确 - 返回的行集可能会随着时间的推移而变化,行可能会很容易出现在结果的许多不同页面上或根本没有页面。
但是,通过查看查询计划来查看何时应用过滤器是很容易的。我将构建一个包含100,000行的简单表FOO
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.
现在,启用autotrace,禁止显示实际数据并运行查询
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
如果您查看查询计划,可以看到我们在应用FOO
谓词之前对rn between 1 and 100
进行了全表扫描。因此整个结果集已实现(并且一致获取的数量大致是表中的块数)。
如果您使用了更合适的分页查询(例如,Tom Kyte有Oracle Magazine article on pagination和更长discussion of pagination on askTom),您会在查询计划中看到SORT ORDER BY STOPKEY
这样的内容告诉你,Oracle知道它可以在某一点之后停止处理。