优化Oracle 11g过程

时间:2011-12-30 16:02:12

标签: oracle optimization stored-procedures oracle11g vldb

我有一个程序来查找一个非常大的表中的一系列事务的第一个,最后一个,最大值和最小价格,该表按日期,对象名称和代码进行组织。我还需要交易数量的总和。表中大约有30亿行,此过程需要很多天才能运行。我想尽可能减少时间。我有一个关于trans表中的distinct字段的索引,并查看查询的select部分的解释计划,正在使用索引。我对另一种方法的建议持开放态度。我使用的是Oracle 11g R2。谢谢。

    declare
    cursor c_iter is select distinct dt, obj, cd from trans;
    r_iter c_iter%ROWTYPE;
    v_fir number(15,8);
    v_las number(15,8);
    v_max number(15,8);
    v_min number(15,8);
    v_tot number;
    begin
    open c_iter;
    loop
        fetch c_iter into r_iter;
        exit when c_iter%NOTFOUND;

      select max(fir), max(las) into v_fir, v_las 
      from 
            ( select 
                first_value(prc) over (order by seq) as "FIR",
                first_value(prc) over (order by seq desc) as "LAS"
              from trans
              where dt = r_iter.DT and obj = r_iter.OBJ and cd = r_iter.CD );

            select max(prc), min(prc), sum(qty) into v_max, v_min, v_tot
            from trans
            where dt = r_iter.DT and obj = r_iter.OBJ and cd = r_iter.CD;

            insert into stats (obj, dt, cd, fir, las, max, min, tot )
            values (r_iter.OBJ, r_iter.DT, r_iter.CD, v_fir, v_las, v_max, v_min, v_tot);

            commit;
    end loop;
    close c_iter;
end;

3 个答案:

答案 0 :(得分:7)

alter session enable parallel dml;

insert /*+ append parallel(stats)*/
into stats(obj, dt, cd, fir, las, max, min, tot)
select /*+ parallel(trans) */ obj, dt, cd
    ,max(prc) keep (dense_rank first order by seq) fir
    ,max(prc) keep (dense_rank first order by seq desc) las
    ,max(prc) max, min(prc) min, sum(qty) tot
from trans
group by obj, dt, cd;

commit;
  • 单个SQL语句通常比多个SQL语句快得多。它们有时需要更多的资源,比如更多的临时表空间,但你的不同光标可能已经在磁盘上对整个表进行排序了。
  • 您可能还想启用并行DML和并行查询,但根据您的对象和系统设置,这可能已经发生。 (并且它可能不一定是好事,取决于您的资源,但它通常有助于大型查询。)
  • 如果SQL写入大量数据,并行写入和APPEND应该可以提高性能,但这也意味着在下次备份之前新表将无法恢复。 (并行DML将自动使用直接路径写入,但我通常包括APPEND,以防并行性无法正常工作。)

即使对于这么小的查询,也要考虑很多,但这是我开始的地方。

答案 1 :(得分:2)

不是我想给出的可靠答案,而是需要考虑的一些事项:

第一个是使用bulk collect。但是,由于您使用的是11g,所以希望这已经为您自动完成了。

每次迭代后你真的需要提交吗?我错了,但我猜这是你最好的消费者之一。

最后,jonearles回答+1。 (我不确定我是否能够将所有内容写入单个SQL查询中,但我也会建议这样做。)

答案 2 :(得分:0)

您可以尝试并行运行查询,有关此here的合理的Oracle白皮书。这不是我曾经不得不使用的Oracle功能,所以我没有第一手经验可以传递。您还需要在Oracle服务器上免费获得足够的资源,以允许您运行将创建的并行进程。