ROW_NUMBER khá kém hiệu quả trong Oracle .
Xem bài viết trong blog của tôi để biết chi tiết về hiệu suất:
- Oracle:ROW_NUMBER đấu với ROWNUM
Đối với truy vấn cụ thể của bạn, tôi khuyên bạn nên thay thế nó bằng ROWNUM và đảm bảo rằng chỉ mục được sử dụng:
SELECT *
FROM (
SELECT /*+ INDEX_ASC(t index_on_column) NOPARALLEL_INDEX(t index_on_column) */
t.*, ROWNUM AS rn
FROM table t
ORDER BY
column
)
WHERE rn >= :start
AND rownum <= :end - :start + 1
Truy vấn này sẽ sử dụng COUNT STOPKEY
Ngoài ra, hãy đảm bảo rằng bạn column không thể nullable hoặc thêm cột WHERE column IS NOT NULL điều kiện.
Nếu không, chỉ mục không thể được sử dụng để truy xuất tất cả các giá trị.
Lưu ý rằng bạn không thể sử dụng ROWNUM BETWEEN :start and :end không có truy vấn con.
ROWNUM luôn được chỉ định cuối cùng và được kiểm tra cuối cùng, đó là cách ROWNUM luôn đi theo thứ tự mà không có khoảng trống.
Nếu bạn sử dụng ROWNUM BETWEEN 10 and 20 , hàng đầu tiên thỏa mãn tất cả các điều kiện khác sẽ trở thành ứng cử viên để trả lại, tạm thời được chỉ định với ROWNUM = 1 và thất bại trong bài kiểm tra ROWNUM BETWEEN 10 AND 20 .
Sau đó, hàng tiếp theo sẽ là một ứng cử viên, được gán với ROWNUM = 1 và thất bại, v.v., vì vậy, cuối cùng, không có hàng nào được trả lại.
Điều này sẽ được giải quyết bằng cách đặt ROWNUM vào truy vấn con.