Имеется проблема со скоростью выполнения сабжа на больших выборках вследствие генерации слишком обобщенного/неоптимального sql-запроса. Смысл в том, что для OrderBy генерируется лишний select пронумеровывающий выбираемое множество, который тормозит на больших выборках из которых нужно получить 1-2-10 первых строк.
речь идет о тройке: First[OrDefault], Single[OrDefault] и Take (без Skip выше по иерархии).
сейчас генерируется такой запрос для GetTable<Table>().FirstOrDefault:
SELECT t2.*
FROM
(
SELECT t.*, ROWNUM as rn
FROM
(
SELECT
t1.*
FROM
t_table t1
ORDER BY
t1.value
) t
) t2
WHERE
t2.rn <= 1
где выделенное лишнее, а достаточно такого:
SELECT * FROM
(
SELECT
t1.*
FROM
t_table t1
ORDER BY
t1.value
)
WHERE ROWNUM <= 1
на маленьких выборках незаметно, но на больших разница на порядки: для примера на выборке в 100к строк первый вариант работает (с индексом) за пол секунды, а второй за сотые доли секунды, не говоря о нагрузке на саму БД!
з.ы. почему упомянул Take — потому, что если в запрос не используется Skip, то так же нет необходимости во внутреннем запросе пронумеровывающем сортированное множество.
з.ы. добавлю также, что в идеале можно залепить еще и хинт FIRST_ROWS(n) на внешний select где идет использование rownum примерно так:
SELECT /*+ FIRST_ROWS(1) */ * FROM
(
SELECT
t1.*
FROM
t_table t1
ORDER BY
t1.value
)
WHERE ROWNUM <= 1
что касается Take вместе со Skip (Pagination), то вот у
Тома можно подсмотреть как наиболее красиво/правильно/оптимально запилить:
select *
from ( select /*+ FIRST_ROWS(n) */
a.*, ROWNUM rnum
from ( your_query_goes_here,
with order by ) a
where ROWNUM <=
:MAX_ROW_TO_FETCH )
where rnum >= :MIN_ROW_TO_FETCH;