Удалить предложение ORDER BY из предложения PARTITION BY? - PullRequest
5 голосов
/ 03 июня 2011

Есть ли способ уменьшить влияние предложения 'ORDER BY lro_pid' в части OVER внутреннего запроса ниже?

SELECT *
  FROM (SELECT a.*, 
               Row_Number() over (PARTITION BY search_point_type 
                                      ORDER BY lro_pid) spt_rank
          FROM lro_search_point a
      ORDER BY spt_rank)
 WHERE spt_rank = 1;

Мне не нужно упорядочивать этот результат в разделе, так как я хочу упорядочить его по другой переменной полностью. lro_pid - это индексированный столбец, но он по-прежнему выглядит пустой тратой ресурсов. (Возможно, есть способ ограничить упорядочение диапазоном одной строки? Надеемся, что на сортировку внутри раздела не будет затрачено никакого времени / энергии)

Ответы [ 3 ]

5 голосов
/ 03 июня 2011

Несколько вещей, чтобы попробовать:

Можете ли вы, например, ORDER BY 'constant' в предложении OVER?

Если упорядочение по константе не разрешено, как насчет ORDER BY (lro_pid * 0)?

Я не эксперт Oracle (MSSQL - это больше всего для меня) - поэтому вопросы для ответа на ваш вопрос!

4 голосов
/ 03 июня 2011

Использование константы в аналитическом ORDER BY в качестве @Will A представляется наиболее быстрым методом.Оптимизатор все еще выполняет сортировку, но это быстрее, чем сортировка столбца.Кроме того, вы, вероятно, хотите удалить второй ORDER BY или хотя бы переместить его во внешний запрос.

Ниже приведен мой тестовый пример:

--Create table, index, and dummy data.
create table lro_search_point(search_point_type number, lro_pid number, column1 number
    ,column2 number, column3 number);
create index lro_search_point_idx on lro_search_point(lro_pid);
insert /*+ append */ into lro_search_point
select mod(level, 10), level, level, level, level from dual connect by level <= 100000;
commit;


--Original version.  Averages 0.53 seconds.
SELECT * FROM 
(
    SELECT a.*, Row_Number() over (PARTITION BY search_point_type ORDER BY lro_pid) spt_rank
    FROM lro_search_point a
    ORDER BY spt_rank
)
WHERE spt_rank=1;


--Sort by constant.  Averages 0.33 seconds.
--This query and the one above have the same explain plan, basically it's
--SELECT/VIEW/SORT ORDER BY/WINDOW SORT PUSHED RANK/TABLE ACCESS FULL.
SELECT * FROM 
(
    SELECT a.*, Row_Number() over (PARTITION BY search_point_type ORDER BY -1) spt_rank
    FROM lro_search_point a
    ORDER BY spt_rank
)
WHERE spt_rank=1;


--Remove the ORDER BY (or at least move it to the outer query).  Averages 0.27 seconds.
SELECT * FROM 
(
    SELECT a.*, Row_Number() over (PARTITION BY search_point_type ORDER BY -1) spt_rank
    FROM lro_search_point a
)
WHERE spt_rank=1;


--Replace analytic with aggregate functions, averages 0.28 seconds.
--This idea is the whole reason I did this, but turns out it's no faster.  *sigh*
--Plan is SELECT/SORT GROUP BY/TABLE ACCESS FULL.
--Note I'm using KEEP instead of just regular MIN.
--I assume that you want the values from the same row.
SELECT a.search_point_type
    ,min(lro_pid) keep (dense_rank first order by -1)
    ,min(column1) keep (dense_rank first order by -1)
    ,min(column2) keep (dense_rank first order by -1)
    ,min(column3) keep (dense_rank first order by -1)
FROM lro_search_point a
group by a.search_point_type;
0 голосов
/ 07 февраля 2012

Чтобы принять предложение ORDER BY, вы можете использовать ORDER BY rownum.

...