Oracleはラベルを使用してバッチ更新データの6つの方式と速度比を行います。


1.情景展示
全部で22 wのデータがあります。 AテーブルのメインキーをBテーブルの指定フィールドに更新する必要がありますが、どのようにして更新が早く完了しますか?
2.ソリューション
宣言:
解決策は一つだけではなく、この文章は快速なマーキング法とコードの実現を紹介します。
二枚の表のIDとID_CARDフィールドはインデックスを作成しました。 
方式一:暗黙的な遊覧標識を使用する(一回更新して1回提出する)

--     
BEGIN
  FOR TEMP_CURSOR IN (SELECT T2.ID, T2.ID_CARD
                        FROM VIRTUAL_CARD10 T1, PRIMARY_INDEX10 T2
                       WHERE T1.ID_CARD = T2.ID_CARD
                         AND T1.REMARK = '** ****   '
                         AND T2.REMARK = '** ****   ') LOOP
    /* LOOP    TEMP_CURSOR(    TEMP_CURSOR) */
    UPDATE VIRTUAL_CARD10
       SET INDEX_ID = TEMP_CURSOR.ID
     WHERE ID_CARD = TEMP_CURSOR.ID_CARD;
    COMMIT; --  
  END LOOP;
END;
実行時間:

方式二:暗黙的な遊覧標識を使用する(1000回更新して1回提出する)(推奨使用)

/*               */
DECLARE
 V_COUNT NUMBER(10);
BEGIN
 /*      */
 FOR TEMP_CURSOR IN (SELECT T2.ID, T2.ID_CARD
            FROM VIRTUAL_CARD10 T1, PRIMARY_INDEX10 T2
            WHERE T1.ID_CARD = T2.ID_CARD
             AND T1.REMARK = '** ****   '
             AND T2.REMARK = '** ****   ') LOOP
  /*      */
  UPDATE VIRTUAL_CARD10
    SET INDEX_ID = TEMP_CURSOR.ID
   WHERE ID_CARD = TEMP_CURSOR.ID_CARD;
  /*     ,+1 */
  V_COUNT := V_COUNT + 1;
  /* 1000   1  */
  IF V_COUNT >= 1000 THEN
   COMMIT; --  
   V_COUNT := 0; --  
  END IF;
 END LOOP;
 COMMIT; --       ,     ,              ,       
END;
実行時間:

方式三:明示的なラベル+バッチ更新(1000条1提出)

/*             */
DECLARE
  V_COUNT    NUMBER(10);
  V_INDEX_ID PRIMARY_INDEX10.ID%TYPE;
  V_ID_CARD  PRIMARY_INDEX10.ID_CARD%TYPE;
  CURSOR TEMP_CURSOR IS
    SELECT T2.ID, T2.ID_CARD
      FROM VIRTUAL_CARD10 T1, PRIMARY_INDEX10 T2
     WHERE T1.ID_CARD = T2.ID_CARD
       AND T1.REMARK = '** ****   '
       AND T2.REMARK = '** ****   ';
BEGIN
  OPEN TEMP_CURSOR;
  LOOP
    /*                  */
    FETCH TEMP_CURSOR
      INTO V_INDEX_ID, V_ID_CARD;
    /*           */
    EXIT WHEN TEMP_CURSOR%NOTFOUND;
    /*      */
    UPDATE VIRTUAL_CARD10
       SET INDEX_ID = V_INDEX_ID
     WHERE ID_CARD = V_ID_CARD;
    /*     ,+1 */
    V_COUNT := V_COUNT + 1;
    /* 1000   1  */
    IF V_COUNT >= 1000 THEN
      COMMIT; --  
      V_COUNT := 0; --  
    END IF;
  END LOOP;
  COMMIT; --       ,     ,              ,       
  CLOSE TEMP_CURSOR;
END;
実行時間:

10000条1提出、実行時間:

方式四:明示的なラベル+配列(一回更新して提出する)(BULK COLLECTを使用する)

/*     +      (        ) */
DECLARE
  /*     :     */
  TYPE TYPE_INDEX_ID IS TABLE OF PRIMARY_INDEX10.ID%TYPE;
  TYPE TYPE_ID_CARD IS TABLE OF PRIMARY_INDEX10.ID_CARD%TYPE;
  /*     */
  V_INDEX_ID TYPE_INDEX_ID;
  V_ID_CARD  TYPE_ID_CARD;
  /*               */
  CURSOR TEMP_CURSOR IS
    SELECT T2.ID, T2.ID_CARD
      FROM VIRTUAL_CARD10 T1, PRIMARY_INDEX10 T2
     WHERE T1.ID_CARD = T2.ID_CARD
       AND T1.REMARK = '** ****   '
       AND T2.REMARK = '** ****   ';
BEGIN
  OPEN TEMP_CURSOR;
  LOOP
    /*   1000             ,    1000    */
    FETCH TEMP_CURSOR BULK COLLECT
      INTO V_INDEX_ID, V_ID_CARD LIMIT 1000;
    /*           */
    EXIT WHEN TEMP_CURSOR%NOTFOUND;
    /*      */
    FOR I IN V_INDEX_ID.FIRST .. V_INDEX_ID.LAST LOOP
      /*      */
      UPDATE VIRTUAL_CARD10
         SET INDEX_ID = V_INDEX_ID(I)
       WHERE ID_CARD = V_ID_CARD(I);
      COMMIT;
    END LOOP;
  END LOOP;
  CLOSE TEMP_CURSOR;
END;
実行時間:

方式5: 明示的なラベル+配列(1000条に1回提出)(BULK COLLECTを使用)

/*     +      (1000     ) */
DECLARE
  /*     :     */
  TYPE TYPE_INDEX_ID IS TABLE OF PRIMARY_INDEX10.ID%TYPE;
  TYPE TYPE_ID_CARD IS TABLE OF PRIMARY_INDEX10.ID_CARD%TYPE;
  /*     */
  V_INDEX_ID TYPE_INDEX_ID;
  V_ID_CARD  TYPE_ID_CARD;
  /*               */
  CURSOR TEMP_CURSOR IS
    SELECT T2.ID, T2.ID_CARD
      FROM VIRTUAL_CARD10 T1, PRIMARY_INDEX10 T2
     WHERE T1.ID_CARD = T2.ID_CARD
       AND T1.REMARK = '** ****   '
       AND T2.REMARK = '** ****   ';
BEGIN
  OPEN TEMP_CURSOR;
  LOOP
    /*   1000              */
    FETCH TEMP_CURSOR BULK COLLECT
      INTO V_INDEX_ID, V_ID_CARD LIMIT 1000;
    /*           */
    EXIT WHEN TEMP_CURSOR%NOTFOUND;
    /*      */
    FOR I IN V_INDEX_ID.FIRST .. V_INDEX_ID.LAST LOOP --  :FOR I IN 1 .. V_INDEX_ID.COUNT LOOP
      /*      */
      UPDATE VIRTUAL_CARD10
         SET INDEX_ID = V_INDEX_ID(I)
       WHERE ID_CARD = V_ID_CARD(I);
      IF I >= V_INDEX_ID.LAST THEN
        COMMIT; --  
      END IF;
    END LOOP;
  END LOOP;
  CLOSE TEMP_CURSOR;
END;
実行時間:

方式六:おすすめの使用(BULK COLLECTとFOALLを使用)

/*     +      (BULK COLLECT FORALL) */
DECLARE
  /*     :     */
  TYPE TYPE_INDEX_ID IS TABLE OF PRIMARY_INDEX10.ID%TYPE;
  TYPE TYPE_ID_CARD IS TABLE OF PRIMARY_INDEX10.ID_CARD%TYPE;
  /*     */
  V_INDEX_ID TYPE_INDEX_ID;
  V_ID_CARD  TYPE_ID_CARD;
  /*               */
  CURSOR TEMP_CURSOR IS
    SELECT T2.ID, T2.ID_CARD
      FROM VIRTUAL_CARD10 T1, PRIMARY_INDEX10 T2
     WHERE T1.ID_CARD = T2.ID_CARD
       AND T1.REMARK = '** ****   '
       AND T2.REMARK = '** ****   ';
BEGIN
  OPEN TEMP_CURSOR;
  LOOP
    /*   1000              */
    FETCH TEMP_CURSOR BULK COLLECT
      INTO V_INDEX_ID, V_ID_CARD LIMIT 1000;
    /*           */
    EXIT WHEN TEMP_CURSOR%NOTFOUND;
    /*      */
    FORALL I IN 1 .. V_INDEX_ID.COUNT--   V_INDEX_ID.FIRST .. V_INDEX_ID.LAST
    /*      */
      UPDATE VIRTUAL_CARD10
         SET INDEX_ID = V_INDEX_ID(I)
       WHERE ID_CARD = V_ID_CARD(I);
    COMMIT; --  
  END LOOP;
  CLOSE TEMP_CURSOR;
END;
実行時間:

Oracle 8から、oracleはPL/SQLのために2つの新しいデータ操作言語(DML)文を導入した。BULK COLLECTとFOALL。
この2つの文はPL/SQL内部で配列処理を行います。BULK COLLECTはデータの高速検索を提供しており、FOALLはINSERT、UDATE、DELETEの操作の性能を大幅に改善することができます。
Oracleデータベースはこれらの語句を使用して、PL/SQLとSQL文の実行エンジンの環境切替回数を大幅に減少させ、その性能を著しく向上させました。 
リボン:
データ量が小さい時は方式二を使ってもいいです。データ量が大きい時は使い方六を勧めます。
インデックスを作成します。
以上はOracleがラベルを使ってバッチ更新を行う6つの方法と速度比の詳しい内容です。Oracleに関するラベルに関する資料は他の関連記事に注目してください。