按条件排序并最大限度地降低执行成本

时间:2018-04-16 16:41:42

标签: sql oracle

我有一个非常有效的光标,但是当我打开它时,有一百万次,我希望它也能以缓慢的方式对行进行排序。

显而易见的解决方案是拥有光标的第二个副本,一个按顺序,另一个没有。

然而,这很乏味,将来容易出错。

问题是:是否有可能使用游标参数强制oracle跳过整个order by子句(当然没有动态sql)?

我想要实现的示例代码:

declare

 cursor c_cur(skip_order varchar2) is
 select /*+ gather_plan_statistics */ xes.x
  from ( select 1 x from dual union all
         select 3 x from dual union all
         select 2 x from dual
  ) xes
 order by case when skip_order = 'Y' then null else xes.x end
 ;
 type t_x is table of c_cur%rowtype;
 tab_xes t_x;
begin
   open c_cur('Y'); -- and sometimes 'N' ...
   fetch c_cur bulk collect into tab_xes;
   close c_cur;
   for info_line in (SELECT *  FROM   TABLE(DBMS_XPLAN.DISPLAY_CURSOR(null,null,'ALL')))
   loop
      dbms_output.put_line(info_line.plan_table_output);
   end loop;
end;

使用“Y”作为参数的内存低于“N”,但排序顺序仍然是......

编辑: 忘了添加: 使用的版本是11.2.0.4

1 个答案:

答案 0 :(得分:2)

  

问题是:是否有可能强迫oracle跳过   整个order by子句使用游标参数(没有动态sql   当然)?

是的,我看到另外两个解决方案,但动态sql看起来更有希望。

其他可能性:

  1. 写2个游标(有和没有顺序),并选择使用哪个。
  2. 使用with子句(oracle应该在执行期间优化此查询 - 因此只查看执行计划会产生误导):
  3.     with no_order as (
        select /*+ gather_plan_statistics */ xes.x
          from ( select 1 x from dual union all
                 select 3 x from dual union all
                 select 2 x from dual
          ) xes
          where skip_order = 'Y'
         ),
         ordered as
         (
           select /*+ gather_plan_statistics */ xes.x
            from ( select 1 x from dual union all
                   select 3 x from dual union all
                   select 2 x from dual
            ) xes
            where skip_order != 'Y'
            order by xes.x
         )
          select *
          from no_order
          union all
          select *
          from ordered
         ;