如何优化此Update语句?

时间:2017-12-01 12:50:48

标签: sql oracle

我有以下更新声明

UPDATE CONTRACTSF CF
SET CF.PAYDATE = (SELECT MAX(FLHTEMP.PAYDATE)
                      FROM FLHTEMP
                      WHERE
                      FLHTEMP.FLHDATE = CF.FLHDATE
                      AND FLHTEMP.FLHCOD = CF.FLHCOD
                      AND FLHTEMP.FLHUN = CF.FLHUN
                      AND FLHTEMP.FLHCONTRACT = CF.FLHCONTRACT)
WHERE CF.FLHUN || CF.FLHCONTRACT || CF.FLHDATE 
        IN (SELECT DISTINCT FT.FLHUN || FT.FLHCONTRACT || FT.FLHDATE 
            FROM FLHTEMP FT)

当FLHTEMP表有大量记录(6M记录)时,需要很长时间才能完成。

我尝试将IN用于多列,而不是将其与||连接但没有区别。

我创建了一个使用的所有列的索引(FLHUN,FLHCONTRACT,FLHCOD,FLHDATE),但是Plan解释显示我没有使用它。

计划解释中显示的代价高昂的操作是散列连接,排序唯一和表格完全访问

2 个答案:

答案 0 :(得分:1)

查询的性能取决于多种因素。如

  • 表格的数据量
  • 已加入列的访问类型
  • 表格访问类型(全扫描/索引扫描/..)

在不知道表结构和解释计划的情况下很难优化查询。

此处的WHERE子句是不必要的,如果您不想更新三列不匹配的记录,那么

  1. 尝试更新CONTRACTSF的所有行:NVL将保留以后加入条件不匹配的值。

    UPDATE CONTRACTSF CF SET CF.PAYDATE = (SELECT NVL(MAX(FLHTEMP.PAYDATE),CF.PAYDATE) FROM FLHTEMP WHERE FLHTEMP.FLHDATE = CF.FLHDATE AND FLHTEMP.FLHCOD = CF.FLHCOD AND FLHTEMP.FLHUN = CF.FLHUN AND FLHTEMP.FLHCONTRACT = CF.FLHCONTRACT)

  2. 或使用EXISTS代替IN

    UPDATE CONTRACTSF CF SET CF.PAYDATE = (SELECT MAX (FLHTEMP.PAYDATE) FROM FLHTEMP WHERE FLHTEMP.FLHDATE = CF.FLHDATE AND FLHTEMP.FLHCOD = CF.FLHCOD AND FLHTEMP.FLHUN = CF.FLHUN AND FLHTEMP.FLHCONTRACT = CF.FLHCONTRACT) WHERE EXISTS (SELECT 1 FROM FLHTEMP FT WHERE FLHTEMP.FLHDATE = CF.FLHDATE AND FLHTEMP.FLHUN = CF.FLHUN AND FLHTEMP.FLHCONTRACT = CF.FLHCONTRACT)

答案 1 :(得分:0)

试试这个。它需要一次flhemp扫描,一次聚合,然后一次散列连接。

merge
 into contractsf cf
using (select flhdate, flhcod, flhun, flhcontract
             ,max(flhtemp.paydate) as max_paydate
         from flhtemp
        group by flhdate, flhcod, flhun, flhcontract
      ) fl
    on(    cf.flhdate     = fl.flhdate
       and cf.flhcod      = fl.flhcod
       and cf.flhun       = fl.flhun
       and cf.flhcontract = fl.flhcontract
      )    
when matched then
   update
      set cf.paydate = fl.max_paydate;