Oracle SQL выбирает отдельный запрос для возврата определенного количества строк - PullRequest
0 голосов
/ 10 августа 2011

У меня есть таблица в базе данных 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 ]

6 голосов
/ 10 августа 2011

Я не уверен, что есть причина не упрощать запрос до этого:

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;
1 голос
/ 10 августа 2011

Вещи, которые я выбрал

  1. Вам следует оставить оптимизацию плана выполнения для СУБД, если вы действительно не знаете лучше
  2. Нет необходимости возвращать повторяющиеся имена из внутреннего подзапроса

Упрощенный запрос с немного другой семантикой:

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.

...