2016-11-29 2 views
0

Ich versuche, eine Massenaktualisierung für eine Tabelle mit etwa 700K Datensätze darin zu tun. Ich muss das effektive Startdatum mit dem effektiven Enddatum des vorherigen Datensatzes aktualisieren. Ich habe Probleme mit der Leistung in der Update-Anweisung, wenn ich die Sub-Abfrage verwende. Es dauert über eine Stunde, um selbst mit einem Filterdatum (7/1/2016-7/15/2016, das ungefähr 2k Datensätze ist) zu laufen. Ich habe es als einfache Update-Anweisung, als Einfügung und in einer Schleife versucht. Der EXPLAIN-Plan, der ROWID anstelle von account_dim_key (PK in der Tabelle) verwendet, ist viel optimaler, jedoch erhalte ich den Fehler, dass die Unterabfrage mehr als eine Zeile zurückgibt. Ich bin mir nicht sicher, warum das mit der ROWID passiert.Bulk Update Startdatum basierend auf dem vorherigen Enddatum

ID ist natürlicher Schlüssel in der Tabelle, account_dim_key ist PK und einzigartig. Beide sind indexiert. Tabelle ist ein Typ 2 SCD.

  1. Wie kann ich die Update-Anweisung ändern ROWID mit
  2. Wäre es optimal sein, eine FORALL Update zu verwenden, und wenn ja, wie würde ich schreiben, dass (neue SQL und unfamliar mit Arrays zum pl)

Anweisung aktualisiert ROWID verwendet, die Fehler einreihige Unterabfrage gibt zurück mehr als eine Zeile, aber mit optimalem erklärt Plan

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-Anweisung mit acocunt_dim_key mit n ot optimal erklären Plan

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) 

Aktualisierung mit Schleife

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 

Antwort

0

Wenn account_dim_key Primärschlüssel ist, dann versuchen Sie 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 

Die Abfrage muss einige Zeit dauern, da es die ganze Tabelle aktualisiert .

Vielleicht können Sie LAG ... (PARTITION BY account_dim_key ORDER BY effective_start_dt) Teil beschleunigen mit einem zusammengesetzten Index auf (account_dim_key, effective_start_dt) Spalten.

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

Allerdings kann Oracle diesen Index ignorieren und den vollständigen Tabellenscan bevorzugen, da die Unterabfrage gegen die gesamte Tabelle gerichtet ist.

Verwandte Themen