2016-01-06 34 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); 
相關問題