我有超过一百万个插入查询要在Oracle SQL Developer中执行,这需要很多时间。有什么办法可以对此进行优化。
答案 0 :(得分:8)
SQL Developer是错误的工具,无法运行1,000,000行按行插入。
SQL * Plus也是如此。
如果您无法编写使用循环或游标进行插入的程序,或者某些pl / sql批量收集,则do what @marmite-bomber suggests-将您的数据写到平面分隔的文本文件中,并设置一个SQL * Loader方案。
Now, you CAN use SQL Developer to do this.
指向分隔的文本文件。
完成后,您将需要执行一组bash或cmd脚本。但是首先,您的计算机上需要一个Oracle客户端-sqlldr程序所在的位置。
它比运行1,000,000个单独的刀片快几个数量级。而且您的DBA不会讨厌您。
使用SQLDev向导,您可以在短短几分钟内启动并运行它。
证明: 我测试了一个简单的场景-我的发现是(details here): SQL * Loader每秒插入10,753条记录 每秒为SQL Developer插入342条记录
SQL * Loader的速度提高了3144%。
答案 1 :(得分:2)
运行单行INSERT
s对于这样的行数是不可行的。
所以一种可能的方法是预处理脚本,仅提取CSV
数据。
这是一个简单的例子
Insert into TAB(COL1,COL2,COL3) values ('1','xxx',to_date('16-10-2018 15:13:49','DD-MM-YYYY HH24:MI:SS'));
Insert into TAB(COL1,COL2,COL3) values ('2','zzzzz',to_date('06-10-2018 15:13:49','DD-MM-YYYY HH24:MI:SS'));
删除所有不相关的部分
'1','xxx','16-10-2018 15:13:49'
'2','zzzzz','06-10-2018 15:13:49'
并使用SQL * Loader或外部表加载此文件。表现会很好。
答案 2 :(得分:0)
我有超过一百万个插入查询要在Oracle SQL Developer中执行
执行任何SQL语句都会产生开销。您要支付该税1000000倍。另外,某些IDE会为工作表中执行的每条SQL语句的结果实例化一个单独的选项卡(单击运行时)。我不记得SQL Developer是否这样做,但是如果这样做,那又是另一笔税,您要支付100万次。
两种可能的优化方式。
通过从dual
中选择值,将单行插入片段转换为集合操作:
insert into your_table
select blah_seq.nextval, q.txt, q.val from (
select 'WHATEVER' as txt, 42 as val from dual union all
select 'AND SO ON' as txt, 23 as val from dual union all
...
);
这将减少开销。为此,需要进行大量的编辑工作。
或者,使用大容量加载选项(例如SQL * Loader或外部表)加载数据。如果您有支持正则表达式的程序员编辑器(例如Notepad ++),则剥离insert
语法并将values
子句转换为CSV行相对简单。
第三种方法是回到产生百万插入语句的源头,并要求它们以更易于管理的格式提供数据,例如数据泵导出。
答案 3 :(得分:0)
另一个建议是进行验证,确认可能的PK列上没有任何重复。插入之前先删除约束,然后再放回去。保持该备用脚本方便。您可以将其作为同一脚本或不同脚本的一部分来执行。同样,如果您不检查是否有重复,则将PK重新设置为期望错误;那么您将使用dups跟踪行并删除该数据。
答案 4 :(得分:0)
您可以将数据块放入集合并批量插入
此外,删除除主键以外的所有索引。数据加载后创建索引
可能有点危险,但是根据数据的质量,您还可以删除外键,然后在导入数据后重新创建它们。您必须确保您的导入不会破坏FK关系
declare
type my_tab is table of mytable%rowtype index by binary_integer;
a_imp my_tab;
begin
-- do stuff to populate a_imp from presumably a text file? or select statement
-- you could chunk your population of the array and bulk insert say 10,000 rows at a time
-- loop through the holding array and import any remaining data
forall ix in 1 .. a_imp.count
insert into [tabel_name] values a_imp(ix);
commit;
end;