Oracle SQL выбирает отдельный запрос для возврата определенного количества строк
У меня есть таблица в базе данных Oracle с столбцом отметки времени nextTime и столбцом строки destName. Также есть больше столбцов, но только эти два имеют отношение в этом случае. Я пытаюсь разработать запрос, который будет возвращать различные destName, имеющие nextTime в течение определенного интервала, и возвращаемое количество строк должно быть максимум одна тысяча. Если в интервале более тысячи различных destName, я хочу, чтобы запрос возвращал тысячу строк, больше или меньше.
У меня фактически есть запрос, который работает, но он слишком медленный:
select destName
from (select /*+ index(tblDestNames tbldestnames_destname)*/ distinct destName
from (select /*+ index(tblDestNames tbldestnames_nextTime)*/ destName
from tblDestNames
where nextTime < :1 and nextTime >= :2 and destName is not null))
where rownum <= 1000;
Любые идеи о том, как разработать более умный запрос или как его оптимизировать, очень ценятся.
2 ответа
Я не уверен, что есть причина не упрощать запрос к этому:
select destName
from (
select distinct destName
from tblDestNames
where nextTime < :1 and nextTime >= :2 and destName is not null
)
where rownum <= 1000;
Однако это не решит проблему с производительностью. Проблема заключается в следующем:
where rownum <= 1000
Заменив rownum на "rank" и "over", вы получите что-то вроде:
select distinct destName
from (
select
destName
from
(select destName, rank()
over (order by destName desc ) rnk
from tblDestNames
where nextTime < :1 and nextTime >= :2 and destName is not null)
where rnk <= 1000;
)
Бонус в том, что с помощью "over" вы выбираете порядок результатов, которые будут отображаться, и тех, которые не будут отображаться.
РЕДАКТИРОВАТЬ: На самом деле это может быть дополнительно упрощено в:
select
distinct destName
from
(select destName, rank()
over (order by destName desc ) rnk
from tblDestNames
where nextTime < :1 and nextTime >= :2 and destName is not null)
where rnk <= 1000;
Вещи, которые я подобрал
- Вы должны оставить оптимизацию плана выполнения СУБД, если вы действительно не знаете лучше
- Нет необходимости возвращать повторяющиеся имена из самого внутреннего подзапроса
Упрощенный запрос с немного другой семантикой:
SELECT destName
FROM (SELECT DISTINCT destName
FROM tblDestNames
WHERE destName IS NOT NULL
AND nextTime NOT BETWEEN :1 and :2)
WHERE rownum <= 1000;
Обратите внимание, что BETWEEN
включительно то есть x BETWEEN y AND z
равняется y <= x <= z
, Чтобы исключить верхнюю границу, вы должны будете либо сделать это так, как делали, либо уменьшить значение параметра:2 на единицу, равную единице nextTime.