Aby wykonać zapytanie top-n wierszy w Oracle, ogólne jest użycie ROWNUM. Więc następujące zapytanie wydaje się ok (dostaje ostatniego 5-płatności):Oracle ROWNUM wydajność
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;
Ale dla bardzo dużych tabel, jest nieefektywne - dla mnie to prowadzony przez ~ 10 minut. Więc próbowałem innych zapytań, a skończyło się tym jednym, która biegnie przez mniej niż sekundę:
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;
, aby dowiedzieć się, co się dzieje, patrzyłem planów wykonania dla każdego zapytania. Dla pierwszej kwerendy:
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
a dla drugiego
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
Oczywiście jest INDEX pełne skanowanie MALEJĄCEJ sprawia, że pierwsze zapytanie nieefektywne dla dużych tabelach. Ale nie mogę naprawdę odróżnić logiki dwóch pytań, patrząc na nie. Czy ktoś mógłby mi wyjaśnić logiczne różnice między dwoma pytaniami w ludzkim języku?
Z góry dziękuję!
id jest zmienną powiązania, nie (powinno być: id?) Jeśli tak, to jaka wartość jest używana (tak samo?) – tbone
Nie sądzę, że 'rownum', którego używasz do filtra w drugiej wersji jest gwarantowane jest to samo, co w pierwszym; myślę, że musisz albo alias swoje drugie zapytanie i odniesienia, lub dodać 'order by rownum' w zapytaniu przeciwko' a'? Wątpię, żeby to miało wpływ na prędkość. –