首先,由于您的内部查询没有进行任何排序,您的查询返回任意 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
如果您查看查询计划,您可以看到我们在应用谓词FOO
之前进行了全表扫描。rn between 1 and 100
所以整个结果集就物化了(一致get的个数大致就是表中的block个数)。
如果您使用了更合适的分页查询(例如,Tom Kyte 有一篇关于分页的Oracle 杂志文章,并且在 askTom上对分页进行了更长的讨论),您会在查询计划中看到这样的SORT ORDER BY STOPKEY
内容,告诉您 Oracle 知道它可以停止在某个点之后进行处理。