Sql 如何优化此更新语句?

Sql 如何优化此更新语句?,sql,oracle,Sql,Oracle,我有以下更新声明 UPDATE CONTRACTSF CF SET CF.PAYDATE = (SELECT MAX(FLHTEMP.PAYDATE) FROM FLHTEMP WHERE FLHTEMP.FLHDATE = CF.FLHDATE AND FLHTEMP.FLHCOD = CF.FLHCOD

我有以下更新声明

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表有大量记录时,需要花费许多小时才能完成

我尝试将IN与多个列一起使用,而不是将其与| |连接起来,但没有任何区别

我为FLHUN、FLHCONTRACT、FLHCOD、FLHDATE中使用的所有列创建了一个索引,但Plan explain向我显示它没有被使用


Plan explain上显示的代价高昂的操作是散列连接、排序唯一和表完全访问。它需要一次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;

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

表的数据量 连接列上的访问类型 表访问类型完整扫描/索引扫描/。。 在不了解表结构和解释计划的情况下,很难优化查询

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

尝试更新合同的所有行sf:NVL将保留后面加入条件不匹配的值

更新合同SF CF 设置CF.PAYDATE=选择NVLMAXFLHTEMP.PAYDATE,CF.PAYDATE 来自FLHTEMP 哪里 FLHTEMP.FLHDATE=CF.FLHDATE 和FLHTEMP.FLHCOD=CF.FLHCOD 和FLHTEMP.FLHUN=CF.FLHUN 和FLHTEMP.FLHCONTRACT=CF.FLHCONTRACT

或使用存在,而不是在

更新合同SF CF 设置CF.PAYDATE= 选择MAX FLHTEMP.PAYDATE 来自FLHTEMP 其中FLHTEMP.FLHDATE=CF.FLHDATE 和FLHTEMP.FLHCOD=CF.FLHCOD 和FLHTEMP.FLHUN=CF.FLHUN 和FLHTEMP.FLHCONTRACT=CF.FLHCONTRACT 哪里有 选择1 来自FLHTEMP FT 其中FLHTEMP.FLHDATE=CF.FLHDATE 和FLHTEMP.FLHUN=CF.FLHUN 和FLHTEMP.FLHCONTRACT=CF.FLHCONTRACT


选择不同的。。。在…中是无用的。。。表示尝试在选择FT.FLHUN、FT.FLHCONTRACT、FT.FLHDATE FROM中的CF.FLHUN、CF.FLHCONTRACT、CF.FLHDATE的位置。。。我已经试过了,但是性能是一样的,如果没有其他东西在进行索引等工作,那么我建议您在两个表中添加一个新列,它将存储这个连接的值CF.FLHUN | | | CF.FLHCONTRACT | CF.FLHDATE。首先尝试将该列添加到一个表中,如果仍然没有显著的改进,则也将其添加到另一个表中。基本上,这将节省Oracle进行连接,然后将其存储在某个位置以便在两个表上进行比较。@avjr除了这个答案,我还将在FLHTEMP FLHDATE、FLHCOD、FLHUN、FLHCONTRACT上创建一个索引,PAYDATE-这样子查询中的所有列都位于您在索引中遗漏PAYDATE的索引中。@avjr第一条语句的行为与原始查询的行为不完全相同请参见答案注释中的解释。选项2是fine,它提供了性能最佳的执行计划,但不幸的是,其行为与原始查询不完全相同。如果两个表在原始statment的WHERE中使用的三列上匹配,但在第四列中不匹配,则PAYDATE将更新为NULL。合并不会改变这样一行。