Archive for May 6th, 2009
Oracle: ROW_NUMBER vs ROWNUM
From Stack Overflow:
I have an SQL query that looks something like this:
SELECT * FROM ( SELECT t.*, row_number() OVER (ORDER BY ID) rn FROM mytable t ) WHERE rn BETWEEN :start and :endEssentially, it's the
ORDER BY
part that's slowing things down. If I were to remove it, theEXPLAIN
cost goes down by an order of magnitude (over 1,000 times).I've tried this:
SELECT t.*, row_number() OVER (ORDER BY ID) rn FROM mytable t WHERE rownum BETWEEN :start and :end, but this doesn't give correct results.
Is there any easy way to speed this up? Or will I have to spend some more time with the
EXPLAIN
tool?
First, just a quick reminder on how ROWNUM
works. From Oracle's documentation:
Conditions testing for
ROWNUM
values greater than a positive integer are always false. For example, this query returns no rows:SELECT * FROM employees WHERE ROWNUM > 1The first row fetched is assigned a
ROWNUM
of 1 and makes the condition false. The second row to be fetched is now the first row and is also assigned aROWNUM
of 1 and makes the condition false. All rows subsequently fail to satisfy the condition, so no rows are returned.
That's why the second query should look like this:
SELECT * FROM ( SELECT t.*, ROWNUM AS rn FROM mytable t ORDER BY paginator, id ) WHERE rn BETWEEN :start and :end
Now, let's see the performance. To do this, we'll create a sample table:
Read the rest of this entry »