Use rownum instead of scrollable resultsets
There are some interesting threads
on AskTom discussing the best method to query a page of records (on Oracle), say records 20 to 30 of a query. Tom Kyte’s advice is to use rownum in the where clause to retrieve only the required rows.
In java there’s another way to query a page of records. You can use a scrollable resultset. You position the cursor on the first record required using absolute(), and then you loop through the number of records you need. Here’s an example.
stmt =
conn.prepareStatement(
"select * from big_table order by object_name",
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
stmt.setFetchSize(pagesize);
rset = stmt.executeQuery();
rset.absolute(start);
The approach adviced by tom kyte is as follows:
stmt =
conn.prepareStatement(
"select * "
+ "from ( select q.* "
+ " , rownum rnum "
+ " from ( select * "
+ " from big_table "
+ " order by object_name "
+ " ) q "
+ " where rownum <= ? "
+ " ) "
+ "where rnum >= ? ");
stmt.setInt(1, end);
stmt.setInt(2, start);
rset = stmt.executeQuery();
The first method is portable, the second is only useable on Oracle.
So, if both perform the same i would prefer to use the scrollable
resultset. This, however is not the case as can be demonstrated using
tkprof. I ran both statements 10 times, querying the first 10 records
with the scrollable resultset, the next with the rownum approach, then
again 10 with the scrollable resultset, etc. In total i queried 200
records, so both statements where created 10 times. Here’s the output
from tkprof:
select *
from
big_table order by object_name
call count cpu elapsed disk query current rows
------- ------------- ---------- ---------- ---------- ---------- ---------------- -----
Parse 10 0.01 0.00 0 0 0 0
Execute 20 0.00 0.00 0 0 0 0
Fetch 110 17.07 287.51 100445 30140 1040 1100-------- ---------- ---------- ---------- ---------- ---------------
total 140 17.08 287.52 100445 30140 1040 1100
Misses in library cache during parse: 0
Optimizer goal: CHOOSE
Parsing user id: 5
Rows Row Source Operation--------------------------------------------------------- -----
20 SORT ORDER BY
221004 TABLE ACCESS FULL BIG_TABLE
*******************************************************************************
select *
from
( select q. , rownum rnum from ( select *
from big_table order by object_name ) q
where rownum <= :1 ) where rnum >= :2
call count cpu elapsed disk query current rows-------- ---------- ---------- ---------- ---------- ---------------- -----
Parse 10 0.00 0.00 0 0 0 0
Execute 10 0.00 0.00 0 0 0 0
Fetch 20 6.11 18.76 30074 30140 0 100-------- ---------- ---------- ---------- ---------- ---------------- ---------------------------------------------------
total 40 6.11 18.76 30074 30140 0 100
Misses in library cache during parse: 0
Optimizer goal: CHOOSE
Parsing user id: 5
Rows Row Source Operation
10 VIEW
20 COUNT STOPKEY
20 VIEW
20 SORT ORDER BY STOPKEY
221004 TABLE ACCESS FULL BIG_TABLE
As you can see from the output of tkprof, the rownum approach is better
for performance. Half the number of executes, and a lot less fetches.
So if you are using an Oracle database, and you’re not going to use
anything else in the future, use the rownum method.
June 8th, 2004 at 8:27 pm
the article is incomplete, missing the tail. The key results are not shown.
October 31st, 2004 at 2:28 am
the article so helpful that make me settle the problem while bother me nearly a week