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.