Take the 2-minute tour ×

Possible Duplicate:
Does Oracle fetch all the rows before evaluating rownum?

If I run the following query on a table with 100k rows

select * from 
 select rownum rownumber, fname, lastname
 from customers
) where rownumber between 1 and 100;

Does Oracle fetch all 100k then filter the list of rows fetched to get the first 100 or does it have a clever way of filtering to the first 100 without fetching all 100k rows?

Is there a way find out how Oracle actually will do the fetch in the above example?

share|improve this question

marked as duplicate by Ben, Kermit, Mat, ruakh, evilone Nov 28 '12 at 6:00


The execution plan will most likely tell you that. –  Magnus Nov 27 '12 at 20:21
If Oracle doesn't optimize this and fetches 100k rows, I want my money back. –  user964970 Nov 27 '12 at 20:23
@user964970, I doubt very much that anyone has ever personally paid for an Oracle licence :-). –  Ben Nov 27 '12 at 20:24
To those that are voting to close, I don't believe this is a duplicate. In the "duplicate" thread, there is an explicit rownum = 1 predicate that the optimizer can use to stop processing after the first row. In this case, there is no explicit rownum predicate so the stop key optimization would not be invoked. –  Justin Cave Nov 27 '12 at 20:39

1 Answer 1

up vote 3 down vote accepted

First, since your inner query isn't doing any sort of ordering, your query returns an arbitrary 100 rows. If this is at attempt to build a query to page through the results, this is not the proper approach both since it is not efficient and because it is not correct-- the set of rows that is returned could well change over time and rows could easily appear on many different pages of the results or no page at all.

It is easy enough, though, to see when the filter is applied by looking at the query plan. I'll build a trivial table FOO with 100,000 rows

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.

Now, enable autotrace, suppress the display of the actual data and run the query

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

|   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)

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

          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

If you look at the query plan, you can see that we did a full table scan of FOO before applying the rn between 1 and 100 predicate. So the entire result set was materialized (and the number of consistent gets is roughly the number of blocks in the table).

If you used a more appropriate pagination query (for example, Tom Kyte has an Oracle Magazine article on pagination and a much longer discussion of pagination on askTom), you would see something in the query plan like SORT ORDER BY STOPKEY that tells you that Oracle knows it can stop processing after a certain point.

share|improve this answer
