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
не допускает значение NULL, либо добавьте условие 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
в подзапрос.
person
Quassnoi
schedule
06.05.2009