Paging with Oracle Paging with Oracle oracle oracle

Paging with Oracle


Something like this should work: From Frans Bouma's Blog

SELECT * FROM(    SELECT a.*, rownum r__    FROM    (        SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%'        ORDER BY OrderDate DESC, ShippingDate DESC    ) a    WHERE rownum < ((pageNumber * pageSize) + 1 ))WHERE r__ >= (((pageNumber-1) * pageSize) + 1)


Ask Tom on pagination and very, very useful analytic functions.

This is excerpt from that page:

select * from (    select /*+ first_rows(25) */     object_id,object_name,     row_number() over    (order by object_id) rn    from all_objects)where rn between :n and :morder by rn;


In the interest of completeness, for people looking for a more modern solution, in Oracle 12c there are some new features including better paging and top handling.

Paging

The paging looks like this:

SELECT *FROM userORDER BY first_nameOFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY;

Top N Records

Getting the top records looks like this:

SELECT *FROM userORDER BY first_nameFETCH FIRST 5 ROWS ONLY

Notice how both the above query examples have ORDER BY clauses. The new commands respect these and are run on the sorted data.

I couldn't find a good Oracle reference page for FETCH or OFFSET but this page has a great overview of these new features.

Performance

As @wweicker points out in the comments below, performance is an issue with the new syntax in 12c. I didn't have a copy of 18c to test if Oracle has since improved it.

Interestingly enough, my actual results were returned slightly quicker the first time I ran the queries on my table (113 million+ rows) for the new method:

  • New method: 0.013 seconds.
  • Old method: 0.107 seconds.

However, as @wweicker mentioned, the explain plan looks much worse for the new method:

  • New method cost: 300,110
  • Old method cost: 30

The new syntax caused a full scan of the index on my column, which was the entire cost. Chances are, things get much worse when limiting on unindexed data.

Let's have a look when including a single unindexed column on the previous dataset:

  • New method time/cost: 189.55 seconds/998,908
  • Old method time/cost: 1.973 seconds/256

Summary: use with caution until Oracle improves this handling. If you have an index to work with, perhaps you can get away with using the new method.

Hopefully I'll have a copy of 18c to play with soon and can update