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 倍(对于 3k 个项目,从超过 30 秒到 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

您还可以在插入操作中添加提示。

将 /*+ 附加 */ 插入制表符 (...) 值 (...)

它改变了 oracle 的工作逻辑,它会运行得更快。

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 回答