Oracle INSERT对大块数据的性能

时间:2012-12-04 14:38:13

标签: performance oracle insert bulk

我正在为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多秒到8- 9k项目的9s) - 但这个逻辑显然不是我想要的那个。

你们可以给我一个提示,我可以在哪里改进我的代码以获得更好的插入数据性能?如果可以做任何改进。

谢谢, Przemek

3 个答案:

答案 0 :(得分: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会立即出现什么问题?

P.S。在'ALTER TABLE'之后你不需要提交,ddl语句会隐式发出它们。

答案 1 :(得分:0)

DDL之后的整个块可以重写为

insert into schema.T_TEST_TABLE (REF_ID, ACTIVE) 
select COLUMN_VALUE, 'Y' FROM TABLE(p_idsCollection);

答案 2 :(得分:0)

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

将/ * +追加* /插入标签(...)值(...)

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

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