Мне показался этот вопрос интересным, поэтому я попробовал несколько вещей.
У меня есть таблица с именем large_t, которая содержит около 1,1 млн строк.
Затем у меня есть два запроса:
select *
from
(
select rownum rnum, a.*
from (
select owner, object_name, object_id
from large_t
order by object_id
) a
where rownum <= 30
) where rnum > 20;
И
select *
from
(
select owner, object_name, object_id,
row_number() over (order by object_id) rnum
from large_t
) where rnum > 20 and rnum <= 30;
Если вы посмотрите на планы, сгенерированные двумя запросами, у первого есть операция:
SORT ORDER BY STOPKEY
В то время как аналитический запрос содержитОперация под названием
WINDOW SORT PUSHED RANK
Операция сортировки ORDER BY STOPKEY - более эффективная операция сортировки, чем обычная операция ORDER BY.Я не уверен, как работает WINDOW SORT PUSHED RANK, но, похоже, он работает аналогичным образом.
Глядя на v $ sql_workarea после выполнения обоих запросов, для обоих требуется только sort_area в 4096 байт.
Напротив, если я выполнил запрос без пейджингового запроса:
select owner, object_name, object_id
from large_t
order by object_id
Тогда требуемая область сортировки составляет 37M, доказывая, что сортировка в обоих запросах примерно одинакова.
Обычно, если вы хотите эффективно возвратить TOP N отсортированного запроса, вам понадобится индекс для столбца сортировки - это предотвратит сортировку Oracle вообще.Итак, я создал индекс для OBJECT_ID, а затем снова объяснил оба запроса.
На этот раз первый запрос использовал индекс и вернулся через 0,2 секунды, тогда как второй запрос не использовал новый индекс и был оченьмедленнее.
Итак, мой вывод из этого небольшого анализа состоит в том, что в общем случае использование rownum для фильтрации или аналитическая функция row_number работают примерно одинаково.Тем не менее, пример rownum автоматически начал использовать индекс, который я создал для таблицы, а row_number - нет.Возможно, я мог бы заставить его использовать индекс с некоторыми подсказками - с этим можно поэкспериментировать.