各位大侠,
我有一个Oracle中SQL语句的效率问题,问题描述如下:
  当前库:A     备份库:B
  在A库上执行如下语句:
      EXEC SQL insert into table1_bak select * from table1 where date <= :date;
     EXEC SQL delete from table1 where date <= :date;
     其中:table1是A库中的表,有5万条当日的流水记录;
           table1_bak是B库的表,通过DB Link的同义词映射到A库上,保存着所有的流水记录,表大小为15G,估计有几千万条记录。       该语句的目的就是\把当天的流水记录备份到历史记录中,然后清表。  这样的两条语句执行下来需要大约20分钟,太慢了。  这种类似的操作很多,一个完整的批处理流程走下来需要2个小时。  哪位专家有优化的方法?可以优化上述的语句或优化表?

解决方案 »

  1.   

    建议把当前表做成是按日分区表,做成31个分区来分别保存每天的数据,你既然是每天都备流水记录为什么where   date   <=   :date;  直接用 date   =   :date 不行吗,你删除表是可以用truncate subpartition应该就可以的
      

  2.   

    如果table1_bak 有索引,触发器之类的,把它们暂时停用!!
    再就是楼上所说的,用truncate删除(提醒一下,truncate删除不能回退)
      

  3.   

    可以试试用 MERGE   INTO 方式插入!!
      

  4.   

    我觉得楼主的当前表只有5万条左右的记录,不应该这么慢。
    1)插入的主要性能瓶颈我觉得可能在网络速度(因为采取db link的方式)以及备份表存在索引、约束。在这样的环境中,备份表的索引、约束都应该被禁用。另外采用insert /*+append*/ into ...的方式会提高插入效率(减少空间计算)
    2)删除应该花费不了多少时间(如果不需要回滚、日志等,可以采用truncate的方式,但对整体性能提升应该不大),主要性能花费应该是在insert上。
    3)前面几位说的采用分区表的方式我不太认同。按照楼主所说是每天都把流水记录转到备份表中去,就是说当前表基本上只存储当天的纪录,那么按日期分区就没什么意义。备份表分区还差不多,但备份表不用来查询。
      

  5.   

    table1上是否在date列上建了索引,表是否被经常分析?
      

  6.   

    才5w多条记录,就需要花20min,我觉得这个跟分区不分区关系不大,当然,分区是一种很好的解决方法。我的数据库里面动则10w以上的数据,而且还有CLOB类型的,备份删除什么的,很快就搞定了呀,所以我认为这个不是语句的错。你可以检查以下系统资源方面的问题。
      

  7.   

    还有就是每次insert时是5万条中的所有数据还是只是一些?table1占用的磁盘空间检查过吗?
      

  8.   

    我觉得还是DB Link的问题,可以看一两个数据库之前的带宽有多大,利用率是怎么样的。
    再分析一下sql是不是能有效的利用到索引,每次执行这个SQL前最好重新分析一下这个table 的索引