4

我有一个在 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

4 回答 4

3

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

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

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
)

如果插入语句源自 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;
于 2013-08-06T11:39:08.980 回答
2

“一个客户报告说,当应用程序和 Oracle 在同一个 LAN 上时它运行良好,但是当他们将 Oracle 服务器移到国外时,他们说程序运行非常缓慢”

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

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

于 2013-08-06T15:36:58.197 回答
0

一些 RDBMS,如 mysql,现在 SQL Server 支持多行插入数据语法:

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

(更多细节在插入多行数据的Sql Server在mysql上插入多行)

但不要预言。很抱歉坏消息。更接近的方法记录在Tech on the Net 上

于 2013-08-06T10:07:54.580 回答
0

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

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

于 2019-10-29T17:49:10.907 回答