2016-11-29 56 views
0

我正在嘗試在其中包含大約700K條記錄的表上執行批量更新。我需要更新有效開始日期和上一條記錄的有效結束日期。使用子查詢時,我在更新語句中的性能遇到問題。即使使用過濾器(7/1/2016-7/15/2016約2k條記錄),也需要花費一個多小時才能運行。我嘗試了它作爲一個簡單的更新語句,插入和循環。使用ROWID而不是account_dim_key(表上的PK)的解釋計劃更爲理想,但是,我得到的錯誤是子查詢返回多行。我不確定爲什麼ROWID發生這種情況。基於上一個結束日期的批量更新開始日期

ID是表上的自然鍵,account_dim_key是PK和唯一的。兩者都被索引。表是2型SCD。

  1. 我要如何使用ROWID
  2. 會更優化使用FORALL更新,如果是我會怎麼寫的更新語句(新PL SQL和unfamliar與陣列)
使用ROWID

Update語句返回錯誤單行子查詢返回多行,但與最佳使用acocunt_dim_key與正說明計劃

UPDATE DEXWHS.D_ACCOUNT_VEEVA 
    SET effective_end_dt = 
      (SELECT prev_dt 
      FROM (SELECT LAG (
          effective_end_dt, 
          1, 
          effective_start_dt) 
          OVER (PARTITION BY account_dim_key 
           ORDER BY effective_start_dt) 
          AS prev_dt, 
          ROWID AS rid 
        FROM dexwhs.d_account_veeva ac2) a 
      WHERE a.rid = ROWID) 

Update語句OT最佳解釋計劃

UPDATE DEXWHS.D_ACCOUNT_VEEVA 
    SET effective_end_dt = 
      (SELECT prev_dt 
      FROM (SELECT LAG (
          effective_end_dt, 
          1, 
          effective_start_dt) 
          OVER (PARTITION BY id 
           ORDER BY effective_start_dt, account_dim_key) 
          AS prev_dt, 
          account_dim_key AS rid 
        FROM dexwhs.d_account_veeva ac2) a 
      WHERE a.rid = account_dim_key) 

更新與循環

CREATE OR REPLACE PROCEDURE PREV_UPDT 
IS 
    CURSOR c1 
    IS 
     SELECT account_dim_key, 
       id, 
       active_flag, 
       effective_end_dt, 
       effective_start_dt, 
       created_date, 
       last_modified_date, 
       (SELECT prev_dt 
        FROM (SELECT LAG (
            effective_end_dt, 
            1, 
            effective_start_dt) 
           OVER (
            PARTITION BY id 
            ORDER BY effective_start_dt, account_dim_key) 
            AS prev_dt, 
           account_dim_key AS rid 
          FROM dexwhs.d_account_veeva ac2) a 
       WHERE a.rid = src.account_dim_key) 
      FROM dexwhs.d_account_veeva src 
     ORDER BY id, effective_start_dt, account_dim_key; 
    r1 c1%ROWTYPE; 
BEGIN 
    OPEN c1; 

    LOOP 
     FETCH c1 INTO r1; 

     EXIT WHEN c1%NOTFOUND; 
     DBMS_OUTPUT.PUT_LINE ('id=' || r1.id); 

     UPDATE dexwhs.D_ACCOUNT_VEEVA trgt 
     SET trgt.effective_start_dt = r1.prev_date, 
      trgt.audit_last_update_dt = SYSDATE, 
     WHERE trgt.account_dim_key = r1.account_dim_key; 

     DBMS_OUTPUT.PUT_LINE ('r1.id_found'); 
    END LOOP; 

    CLOSE c1; 
END 

回答

0

如果account_dim_key是主鍵,然後嘗試MERGE

MERGE INTO dexwhs.d_account_veeva a 
USING (
    SELECT account_dim_key, 
      LAG (effective_end_dt, 1, effective_start_dt) 
      OVER (PARTITION BY account_dim_key 
       ORDER BY effective_start_dt) 
      AS prev_dt 
    FROM dexwhs.d_account_veeva 
) b 
ON (a.account_dim_key = b.account_dim_key) 
WHEN MATCHED THEN UPDATE SET a.effective_end_dt = b.prev_dt 

查詢,因爲它是更新整個表必須花費一些時間。

也許您可以使用(account_dim_key, effective_start_dt)列上的複合索引加速LAG ... (PARTITION BY account_dim_key ORDER BY effective_start_dt)部分。

CREATE INDEX some_name 
ON dexwhs.d_account_veeva(account_dim_key, effective_start_dt) 

但是,由於子查詢是針對整個表,所以Oracle可以忽略此索引並更喜歡全表掃描。

相關問題