1

私は Oracle 10g のストアド プロシージャを開発していますが、約 2 ~ 3k の項目のリストをプロシージャに渡そうとしているときに、かなり重いパフォーマンスのボトルネックにぶつかっています。これが私のコードです:

TYPE ty_id_list
  AS TABLE OF NUMBER(11);

----------------------------------------------------------


PROCEDURE sp_performance_test (
  p_idsCollection IN schema.ty_id_list )
AS

TYPE type_numeric_table IS TABLE OF NUMBER(11) INDEX BY BINARY_INTEGER;
l_ids type_numeric_table;
data type_numeric_table;
empty type_numeric_table;

BEGIN

EXECUTE IMMEDIATE
  'ALTER TABLE schema.T_TEST_TABLE NOLOGGING';
COMMIT;

SELECT COLUMN_VALUE BULK COLLECT INTO l_ids 
  FROM TABLE(p_idsCollection);

FOR j IN 1 .. l_ids.COUNT LOOP
  data(data.count+1) := l_ids(j);

  IF(MOD(data.COUNT,500) = 0 ) THEN
    FORALL i IN 1 .. data.COUNT
      INSERT INTO schema.T_TEST_TABLE (REF_ID, ACTIVE)
      VALUES (data(i), 'Y');  
  data := empty;
  END IF;
END LOOP;
IF(data.count IS NOT NULL) THEN
  FORALL i IN 1 .. data.COUNT
    INSERT INTO schema.T_TEST_TABLE (REF_ID, ACTIVE)
    VALUES (data(i), 'Y'); 
END IF;
COMMIT;

EXECUTE IMMEDIATE
  'ALTER TABLE schema.T_TEST_TABLE LOGGING'; 
COMMIT;

END sp_performance_test;

したがって、プロセスに非常に大幅に追加されるのは、次の部分のようです: data(data.count+1) := l_ids(j) ; コレクションからの要素の取得をスキップして、この行を data(data.count+1) := j ; に変更すると、プロシージャの実行時間は 3 ~ 4 倍速くなります (30 秒以上から 3k アイテムの場合は 8 ~ 9 秒)。このロジックは明らかに私が望むものではありません。

データ挿入のパフォーマンスを向上させるためにコードを改善できるヒントを教えてください。本当に改善できれば。

ありがとう、プレゼメク

4

3 に答える 3

0

私はあなたの論理に従わない。

コレクションを受け入れます。別のコレクションにコピーします。

SELECT COLUMN_VALUE BULK COLLECT INTO l_ids 
  FROM TABLE(p_idsCollection);

そして、ループでもう一度コピーします。

FOR j IN 1 .. l_ids.COUNT LOOP
  data(data.count+1) := l_ids(j);

そしてその後、500列のチャンクバルクインサートを実行することができます。p_idsCollectionすぐに一括挿入することの何が問題になっていますか?

ps'ALTER TABLE'の後にコミットする必要はありません。ddlステートメントは、それらを暗黙的に発行します。

于 2012-12-04T14:59:41.810 に答える
0

挿入操作にヒントを追加することもできます。

/ *+追加*/をタブ(...)値(...)に挿入します

これは、オラクルの作業ロジックを変更するものであり、より高速に動作します。

http://www.dba-oracle.com/t_insert_tuning.htm

于 2012-12-16T05:59:43.570 に答える
0

DDL の後のブロック全体は、次のように書き換えることができます。

insert into schema.T_TEST_TABLE (REF_ID, ACTIVE) 
select COLUMN_VALUE, 'Y' FROM TABLE(p_idsCollection);
于 2012-12-04T15:04:26.620 に答える