Oracle 11g - 插入多行的最有效方法

时间:2013-08-06 08:30:09

标签: sql oracle networking oracle11g sql-tuning

我有一个在WAN上运行缓慢的应用程序 - 我们认为原因是多次插入表中。我目前正在寻找更有效的方法来同时插入多行。

我找到了这个方法:

INSERT ALL
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (100,20)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (21,2)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (321,10)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (22,13)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (14,121)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (11,112)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (112,23)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (132,2323)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (121,34)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (24333,333)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (1232,3434)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (4554,3434)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (3434,211)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (3434,1233)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (12,22)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (356,233)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (9347,23)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (8904,245)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (342,4545)
  INTO MULTI_INSERT(VAL_1, VAL_2) VALUES (453,233)
SELECT 1 FROM DUAL;

我想知道的是:上面的方法实际上比仅仅执行20“INSERT INTO MY_TABLE(1,1)”更有效;“?还有其他方法吗?

4 个答案:

答案 0 :(得分:3)

您可以尝试direct path insert来加快操作速度,但是对于100条记录,常规路径插入必须足够快,而且似乎问题是关于从大量源插入日志时的表锁定。

要指示Oracle使用直接路径插入,必须根据插入语句语法指定APPENDAPPEND_VALUES 提示。 E.g。

insert /*+ APPEND */ 
into multi_insert(val_1, val_2)
select * from (
  select 100,    20 from dual union all
  select 21,      2 from dual union all
  select 321,    10 from dual union all
  select 22,     13 from dual union all
  select 14,    121 from dual union all
  select 11,    112 from dual union all
  select 112,    23 from dual union all
  select 132,  2323 from dual union all
  select 121,    34 from dual union all
  select 24333, 333 from dual union all
  select 1232, 3434 from dual union all
  select 4554, 3434 from dual union all
  select 3434,  211 from dual union all
  select 3434, 1233 from dual union all
  select 12,     22 from dual union all
  select 356,   233 from dual union all
  select 9347,   23 from dual union all
  select 8904,  245 from dual union all
  select 342,  4545 from dual union all
  select 453,   233 from dual
)

如果insert语句来自PL / SQL代码,那么您可以使用带有forall语句的批量插入来提高性能(SQLFiddle):

declare
  type TRowList is table of multi_insert%rowtype index by binary_integer;

  vRowList TRowList;
  vRow     multi_insert%rowtype;
begin


  vRow.val_1 := 100;
  vRow.val_2 := 20;
  vRowList(0) := vRow;

  vRow.val_1 := 21;
  vRow.val_2 := 2;
  vRowList(1) := vRow;

  vRow.val_1 := 321;
  vRow.val_2 := 10;
  vRowList(2) := vRow;

  -- ...

  forall vIdx in vRowList.first .. vRowList.last
        insert /*+ APPEND_VALUES */  -- direct path insert
        into multi_insert values vRowList(vIdx);

end;

答案 1 :(得分:2)

  

“一位客户报告说它在应用程序时运行良好   和Oracle在同一个局域网上,但当他们移动他们的Oracle时   国外服务器他们说该程序运行速度非常慢“

好的,现在我们到了某个地方。如果您有一个设置,其中您的百个语句是单独的呼叫,它们可能会在单独的数据包中发送。与LAN相比,WAN上的这种情况会很痛苦。在这种情况下,将RBAR语句转换为基于集合的语句是否会减少传输数据包的数量是值得的。

但是,在推出更改之前,我仍然建议您先了解一些事实。您的客户端是否有可以与之交谈的网络管理员?或者至少可以让他们安装Wireshark并向您发送一些报告吗?

答案 2 :(得分:0)

某些RDBMS如mysql和现在的SQL Server支持多行插入数据语法:

Insert into myTable ( c1, c2 ) values
( 1,1 ),
( 1,2 ),
... ;

Inserting multiple rows of data of Sql Serverinserting multirow on mysql中的更多详情)

但不要oracle。对坏消息感到抱歉。在Tech on the Net上记录了更为接近的方式。

答案 3 :(得分:0)

Oracle不支持多行插入,请使用下一个选项:

插入方法(名称)值(“ GET”); 插入方法(名称)值(“ POST”);