Để truy vấn top-n hàng trong Oracle, nói chung là sử dụng ROWNUM. Vì vậy, các truy vấn sau đây có vẻ ok (được 5 thanh toán gần đây nhất):Hiệu suất ROWNUM của Oracle
select a.paydate, a.amount
from (
select t.paydate, t.amount
from payments t
where t.some_id = id
order by t.paydate desc
) a
where rownum <= 5;
Nhưng đối với bảng rất lớn, nó không hiệu quả - đối với tôi nó chạy ~ 10 phút. Vì vậy, tôi đã cố gắng truy vấn khác, và tôi đã kết thúc với một này mà chạy cho ít hơn một giây:
select *
from (
select a.*, rownum
from (select t.paydate, t.amount
from payments t
where t.some_id = id
order by t.paydate desc) a
)
where rownum <= 5;
Để tìm hiểu những gì đang xảy ra, tôi nhìn kế hoạch thực hiện cho mỗi truy vấn. Đối với truy vấn đầu tiên:
SELECT STATEMENT, GOAL = ALL_ROWS 7 5 175
COUNT STOPKEY
VIEW 7 5 175
TABLE ACCESS BY INDEX ROWID 7 316576866 6331537320
INDEX FULL SCAN DESCENDING 4 6
Và đối với thứ hai:
SELECT STATEMENT, GOAL = ALL_ROWS 86 5 175
COUNT STOPKEY
VIEW 86 81 2835
COUNT
VIEW 86 81 1782
SORT ORDER BY 86 81 1620
TABLE ACCESS BY INDEX ROWID 85 81 1620
INDEX RANGE SCAN 4 81
Rõ ràng, đó là INDEX ĐẦY ĐỦ SCAN Giảm dần mà làm cho truy vấn đầu tiên không hiệu quả cho các bảng lớn. Nhưng tôi không thể phân biệt được logic của hai truy vấn bằng cách nhìn vào chúng. Bất cứ ai có thể giải thích cho tôi sự khác biệt hợp lý giữa hai truy vấn bằng ngôn ngữ của con người?
Cảm ơn trước!
id là biến số liên kết, không (phải là: id?) Nếu vậy, giá trị nào được sử dụng (giống nhau?) – tbone
Tôi không nghĩ rằng 'rownum' bạn đang sử dụng cho bộ lọc trong phiên bản thứ hai là được đảm bảo giống như trong lần đầu tiên; nghĩ rằng bạn cần phải bí danh truy vấn thứ hai của bạn và tham chiếu đó, hoặc thêm 'thứ tự bởi rownum' trong truy vấn đối với' a'? Tôi nghi ngờ điều này đang ảnh hưởng đến tốc độ mặc dù. –