从PARTITION BY子句中删除ORDER BY子句



有没有办法减少下面内部查询OVER部分中ORDER BY lro_pid子句的影响?

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是一个索引列,但就目前情况来看,这似乎仍然是在浪费资源。(也许有一种方法可以将排序限制在一行的范围内??希望在分区内根本不会花费时间/精力进行排序)

要尝试的几件事:

你能举例说明OVER子句中的ORDER BY 'constant'吗?

如果不允许按常数排序,那么ORDER BY (lro_pid * 0)如何?

我不是Oracle专家(MSSQL更像是我的专长)-因此有问题可以回答您的问题!

如@Will a所建议的那样在分析ORDER BY中使用常量似乎是最快的方法。优化器仍然执行排序,但它比排序列更快。此外,您可能希望删除第二个ORDERBY,或者至少将其移动到外部查询。

下面是我的测试用例:

--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;

要获得子句ORDER BY,可以使用ORDER BY rownum。

相关内容

  • 没有找到相关文章

最新更新