rails / arel

A Relational Algebra
2.06k stars 390 forks source link

Oracle limit and offset issue when query is ordered #99

Closed berislavbabic closed 11 years ago

berislavbabic commented 12 years ago

A weird issue happens when your query is ordered, and then paginated to include limit and offset. It returns last couple of rows(this is weird, because there is no strict number the database will return) for all pages, and after few pages it just freezes the query and returns the same rows for any offset and limit. This is all tested on oracle 11gR2x64, I also ran the query in SQLDeveloper and got the same results. So it's a database problem. I found a workaround that works, and i will make a pull request that solves this issue, at least for me, it should probably be tested by someone else.

tenderlove commented 12 years ago

Merged your change, so I'm closing this. Thanks!

t0m commented 11 years ago

I ran into this too and the reason the results "freeze" like that is explained a bit in this ask tom article under the "Pagination with ROWNUM" section. In a nutshell, oracle requires that your order by clause contains a unique column or the results will be non-deterministic.

The submitted fix will work but it comes with a couple performance penalties:

I've found that changing the paging query from:

WHERE raw_rnum_ between #{offset.expr.to_i + 1 } and #{offset.expr.to_i + limit}

to:

WHERE raw_rnum_ >= #{offset.expr.to_i + 1 } and rownum <= #{limit}

gives the same results but with both of the optimizations added back in. I've made the changes in this branch and the results are noticeably quicker on my app. Could anyone else give a quick double check to make sure they see the same performance gains?

eduardordm commented 11 years ago

Hey @t0m, the upper bound needs to be limited within the query, not outside of it. The @babinho commit is completely broken and it should be reverted, the original issue is way less damaging than the current one (and I couldn't reproduce actually). I think this issue didn't get visibility because most oracle users are larger companies that are still on older versions like mine.

@tenderlove please revert this commit, save us.