ROW_NUMBER
е доста неефективно в Oracle
.
Вижте статията в моя блог за подробности за ефективността:
- Oracle:ROW_NUMBER срещу ROWNUM
За вашата конкретна заявка бих ви препоръчал да я замените с ROWNUM
и се уверете, че се използва индексът:
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
Тази заявка ще използва COUNT STOPKEY
Също така се уверете, че сте column
не може да бъде нула или добавете WHERE column IS NOT NULL
състояние.
В противен случай индексът не може да се използва за извличане на всички стойности.
Имайте предвид, че не можете да използвате ROWNUM BETWEEN :start and :end
без подзаявка.
ROWNUM
винаги се присвоява последен и се проверява последен, така е ROWNUM
Винаги се подреждат без пропуски.
Ако използвате ROWNUM BETWEEN 10 and 20
, първият ред, който отговаря на всички останали условия, ще стане кандидат за връщане, временно присвоен с ROWNUM = 1
и се провали на теста на ROWNUM BETWEEN 10 AND 20
.
След това следващият ред ще бъде кандидат, присвоен с ROWNUM = 1
и неуспешен и т.н., така че накрая няма да бъдат върнати никакви редове.
Това трябва да се заобиколи, като се постави ROWNUM
е в подзаявката.