2

我有一个程序可以在一个按日期、对象名称和代码组织的非常大的表中找到一系列交易的第一个、最后一个、最高和最低价格。我还需要交易数量的总和。表中有大约 30 亿行,这个过程需要很多天才能运行。我想尽可能地缩短那段时间。我在 trans 表中的不同字段上有一个索引,并查看查询选择部分的解释计划,正在使用该索引。我愿意接受有关替代方法的建议。我使用 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;
4

3 回答 3

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 以防并行性无法正常工作。)

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

于 2011-12-30T17:02:28.077 回答
2

不是我想给出的可靠答案,但有几点需要考虑:

第一种是使用批量收集。但是,由于您使用的是 11g,因此希望这已经自动为您完成了。

你真的需要在每次迭代后提交吗?我可能是错的,但我猜这是你的顶级消费者之一。

最后,为 jonearles 的回答 +1。(我不确定是否可以将所有内容都写到一个 SQL 查询中,但我也会建议这样做。)

于 2011-12-30T16:14:58.777 回答
0

您可以尝试使查询并行运行,这里有一个合理的 Oracle 白皮书。这不是我曾经必须自己使用的 Oracle 功能,因此我没有第一手的经验可以传递。您还需要在 Oracle 服务器上拥有足够的可用资源,以允许您运行这将创建的并行进程。

于 2011-12-30T16:43:17.650 回答