ROW_NUMBER
довольно неэффективно в Oracle
.
Подробнее о производительности смотрите в статье в моем блоге:
Для вашего конкретного запроса я бы порекомендовал заменить его на 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
не имеет значения nullable, или добавьте условие 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
в подзапрос.