2016-01-06 33 views
0
MERGE INTO ////////1 GFO 
      USING 
      (SELECT * 
    FROM 
    (SELECT facto/////rid, 
     p-Id, 
     PRE/////EDATE, 
     RU//MODE, 
     cre///date, 
     ROW_NUMBER() OVER (PARTITION BY facto/////id ORDER BY cre///te DESC) col 
    FROM ///////////2 
    ) x 
    WHERE x.col = 1) UFD 
      ON (GFO.FACTO-/////RID=UFD.FACTO////RID) 
      WHEN MATCHED THEN UPDATE 
      SET 
      GFO.PRE////DATE=UFD.PRE//////DATE 
      WHERE UFD.CRE/////DATE IS NOT NULL 
      AND UFD.RU//MODE= 'S' 
      AND GFO.P////ID=:2 

喜every1,我上面的MERGE语句花费的时间太长,它必须使用表2分别具有4millions在表1中运行40次加记录,为40个不同的p - id,请建议更有效的方式,目前它需要40+分钟。 其更新使用一列从table2.t只有一个colummn我怎样才能使这个合并/更新语句更加高效,其花费过多时间

我无法执行查询,其返回 错误:无法获取最后从PLAN_TABLE解释计划 EXPLAIN PLAN IMAGE

这里是解释计划截图

cost

+0

您能否为此查询显示解释计划?只需运行'EXPLAIN PLAN FOR MERGE ..........',然后'SELECT * FROM table(DBMS_XPLAN.Display)',然后复制此查询的结果(作为文本)并将其追加到题。 – krokodilko

+0

是否有'GFO.P //// ID','GFO.FACTO - ///// RID'和'UFD.FACTO //// RID'的选择性索引?如果是这样,请将GFO加入到您的'SELECT'语句中并在其中应用'GFO.P //// ID =:2'过滤器。 –

+0

目前还不清楚为什么这需要运行40次,而不是在'on'中有一个额外的条件为所有的40'p - id'值运行一次。 –

回答

1

所显示的计划似乎被确定,观察到的问题从遍历P_ID不扩展造成的。

我想你执行这样的事情(强烈简化) - 假设P_ID要处理是在表TAB_PID

begin 
for cur in (select p_id from tab_pid) loop 
merge INTO tab1 USING tab2 ON (tab1.r_id = tab2.r_id) 
WHEN MATCHED THEN 
    UPDATE SET tab1.col1=tab2.col1 WHERE p_id = cur.p_id; 
end loop; 
end; 
/

HASH随经过60秒时是JOIN在大表(否PARALLEL模式)不是灾难性的结果。但循环40次使你的40分钟。

所以我很乐意尝试将循环集成到MERGE语句中,而无需知道类似这样的细节(mayby您还需要ajdust MERGE JOIN条件)。

merge INTO tab1 USING tab2 ON (tab1.r_id = tab2.r_id) 
WHEN MATCHED THEN 
    UPDATE SET tab1.col1=tab2.col1 
    WHERE p_id in (select p_id from tab_pid); 
相关问题