在 Oracle 中插入一百万行的最快方法
Posted
技术标签:
【中文标题】在 Oracle 中插入一百万行的最快方法【英文标题】:Fastest way to insert a million rows in Oracle 【发布时间】:2013-08-24 03:07:27 【问题描述】:如何以最佳方式在 Oracle 中为以下过程插入超过一百万行?如果我将 FOR 循环增加到一百万行,它就会挂起。
create or replace procedure inst_prc1 as
xssn number;
xcount number;
l_start Number;
l_end Number;
cursor c1 is select max(ssn)S1 from dtr_debtors1;
Begin
l_start := DBMS_UTILITY.GET_TIME;
FOR I IN 1..10000 LOOP
For C1_REC IN C1 Loop
insert into dtr_debtors1(SSN) values (C1_REC.S1+1);
End loop;
END LOOP;
commit;
l_end := DBMS_UTILITY.GET_TIME;
DBMS_OUTPUT.PUT_LINE('The Procedure Start Time is '||l_start);
DBMS_OUTPUT.PUT_LINE('The Procedure End Time is '||l_end);
End inst_prc1;
【问题讨论】:
我不建议为此使用光标。因为光标会降低您的性能。 查看link 【参考方案1】:您的方法会导致内存问题。最快的方法是[在大卫发表评论后编辑查询以处理空场景]:
insert into dtr_debtors1(SSN)
select a.S1+level
from dual,(select nvl(max(ssn),0) S1 from dtr_debtors1) a
connect by level <= 10000
选择插入是最快的方法,因为所有内容都保留在 RAM 中。 如果它滑入全局临时区域,此查询可能会变慢,但随后需要数据库调整。我认为没有比这更快的了。
关于 Query 使用内存的更多细节:
每个查询都有自己的 PGA [程序全局区域],基本上是每个查询可用的 RAM。如果这个区域不足以返回查询结果,则 SQL 引擎开始使用像硬盘一样的 Golabl 临时表空间,并且查询开始变慢。如果查询需要的数据太大,甚至临时区域都不够用,那么就会出现表空间错误。
所以始终设计查询,使其留在 PGA 中,否则它是一个危险信号。
【讨论】:
这个查询不会使用临时表空间,它会先以ORA-30009: Not enough memory for CONNECT BY operation
失败。这有点奇怪,因为您可以通过alter session set workarea_size_policy=manual;
和alter session set sort_area_size=<large number>;
解决错误。显然不是所有的“排序”都可以使用临时表空间。
如果 dtr_debtors1 为空,那么您将在表中插入空值。使用 Coalesce(max(ssn),0)。【参考方案2】:
在循环中使用单个 insert
语句一次插入一行很慢。最快的方法是像下面这样使用insert-select
,它会生成一百万行和批量插入。
insert into dtr_debtors1(SSN)
select level from dual connect by level <= 1000000;
【讨论】:
【参考方案3】:尝试删除在您的表上创建的所有索引,然后尝试使用select
查询插入。你可以试试这个链接,它将帮助你在inserting millions of rows 中快速进入你的数据库。
【讨论】:
【参考方案4】:1) 如果要使用 PL/SQL 插入,则使用 BULK COLLECT INTO
,插入 DML 使用 BULK BIND FOR ALL
。
2) 在 SQL 多插入中使用INSERT ALL
语句。
3) 另一种方法INSERT INTO <tb_nm> SELECT
。
4) 使用SQL LOADER
实用程序。
【讨论】:
以上是关于在 Oracle 中插入一百万行的最快方法的主要内容,如果未能解决你的问题,请参考以下文章