如何在 Oracle SQL Developer 中执行超过 100 万条插入查询?
Posted
技术标签:
【中文标题】如何在 Oracle SQL Developer 中执行超过 100 万条插入查询?【英文标题】:How to execute more than 1 million insert queries in Oracle SQL Developer? 【发布时间】:2018-10-16 11:07:21 【问题描述】:我有超过 100 万个插入查询要在 Oracle SQL Developer 中执行,这需要很多时间。有什么办法可以优化这个。
【问题讨论】:
您有查询还是有 100 万行的数据?您的数据库是在 Oracle SQL Developer 还是 mysql?当前数据在哪里? 将数据放入文件并从文件中加载数据。 @ChetanRanpariya 我有 100 万个查询,数据库是 Oracle SQL Developer Execute scripts by relative path in Oracle SQL Developer的可能重复 我建议你把所有的插入都放在一个 .sql 中,然后复制到数据库服务器上,然后在 Sql+ 命令提示符下运行。 【参考方案1】:SQL Developer 是运行 1,000,000 行逐行插入的错误工具。
SQL*Plus 也是如此。
如果您无法编写程序来使用循环或游标或某些 pl/sql 批量收集来执行插入操作,那么 do what @marmite-bomber suggests - 将您的数据写入一个平面分隔的文本文件,并设置一个 SQL*加载程序场景。
Now, you CAN use SQL Developer to do this.
指向您的分隔文本文件。
映射所有内容,然后使用此 IMPORT 方法。
完成后,您将拥有一组需要执行的 bash 或 cmd 脚本。但首先,您的机器上需要一个 Oracle 客户端 - 这就是 sqlldr 程序所在的位置。
这比运行 1,000,000 个单独的插入要快几个数量级。而且您的 DBA 不会讨厌您。
使用 SQLDev 向导,您可以在几分钟内启动并运行它。
证明: 我测试了一个简单的场景 - 我的发现是 (details here): SQL*Loader 每秒插入 10,753 条记录 SQL Developer 每秒插入 342 条记录
SQL*Loader 速度提高了 3,144%。
【讨论】:
您是否真的测量过,通过 SQLDeveloper 的脚本运行器实用程序将 1M 插入作为一次性操作运行比这种方法慢 那么多还安装了 Oracle 客户端并可能设置了tnsnames.ora
等?我的意思是,OP 可以使用他们现有的工具来完成这项工作。
@MickMnemonic 是的,我有。 sqlldr 可以在几秒钟内加载 1M 条记录,尤其是如果您查看 sqlldr 带来的直接路径、并行和其他注重性能的特性。
@MickMnemonic 如果您要定期进行任何大小的数据加载,花时间设置适当的工具将是值得的。如果这是一个完成,那么当然,继续并使用 SQLDev 运行您的脚本。
那么使用 SQLDeveloper 花了多长时间?而且我知道 SQLLoader 对于“真正的”数据迁移/转换非常有用。
@MickMnemonic 在我今天刚刚运行的场景中,SQL*loader 比 SQL Developer 快 3,144%。【参考方案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 或外部表加载此文件。性能会很好。
【讨论】:
【参考方案3】:另一个建议是验证您在可能的 PK 列上没有任何重复。在插入之前删除约束,并在完成后将它们放回原处。将更改脚本放在手边。您可以将其作为相同脚本或不同脚本的一部分来执行。同样,如果您不检查 dups 并把 PK 放回预期错误;那么您将使用 dups 追踪行并删除该数据。
【讨论】:
【参考方案4】:我有超过 100 万个插入查询要在 Oracle SQL Developer 中执行
执行任何 SQL 语句都会产生开销。你支付了 1000000 次税。此外,一些 IDE 为在工作表中执行的每个 SQL 语句的结果实例化一个单独的选项卡(当单击运行时)。我不记得 SQL Developer 是否这样做了,但如果这样做了,那就是你要支付 1000000 倍的另一种税。
两种可能的优化。
通过从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 行相对简单。
第三种方法是返回生成数百万条插入语句的源,并要求它们以更易于管理的格式提供数据,例如数据泵导出。
【讨论】:
在UNION ALL
查询中应注意避免ORA-02287: sequence number not allowed here。
@MarmiteBomber - 感谢您在午餐前发现草率的伪代码;)【参考方案5】:
您可以将数据块放入集合并批量插入
另外,删除除主键之外的所有索引。数据加载后创建索引
可能有点危险,但根据数据的质量,您还可以删除外键,然后在导入数据后重新创建它们。您必须确保您的导入不会破坏 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;
【讨论】:
以上是关于如何在 Oracle SQL Developer 中执行超过 100 万条插入查询?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SQL Developer 中检查语法 Oracle 存储过程?
oracle 客户端 sql developer 如何修改jdk版本