我正在用 PL/SQL 编写数据转换,用于处理数据并将其加载到表中。根据 PL/SQL Profiler,转换中最慢的部分之一是实际插入到目标表中。该表有一个索引。
为了准备加载数据,我使用表的行类型填充一个变量,然后将其插入到表中,如下所示:
insert into mytable values r_myRow;
似乎我可以通过执行以下操作来获得性能:
- 在插入期间关闭日志记录
- 一次插入多条记录
这些方法是否可取?如果是这样,语法是什么?
最好一次插入几百行,使用 PL/SQL 表和 FORALL 绑定到插入语句中。有关这方面的详细信息,请参见此处。
还要注意如何构造 PL/SQL 表。如果可能的话,宁愿直接在 SQL 中使用“INSERT INTO t1 SELECT ...”进行所有转换,因为在 PL/SQL 中进行逐行操作仍然比 SQL 慢。
无论哪种情况,您也可以通过 using 使用直接路径插入INSERT /*+APPEND*/
,这基本上绕过了 DB 缓存,直接将新块分配并写入数据文件。这也可以减少日志记录的数量,具体取决于您如何使用它。这也有一些含义,所以请先阅读精美的手册。
最后,如果您要截断并重建表,那么首先删除(或标记为不可用)然后重建索引可能是值得的。
常规插入语句是在表中获取数据的最慢方法,不适用于批量插入。以下文章引用了许多不同的技术来提高性能:http ://www.dba-oracle.com/oracle_tips_data_load.htm
删除索引,然后插入行,然后重新创建索引。
如果删除索引的速度不够快,则需要Oracle SQL*Loader:
http://www.oracle.com/technology/products/database/utilities/htdocs/sql_loader_overview.html
假设您参加了 eid,ename,sal,job。所以首先创建一个表:
SQL>create table tablename(eid number, ename varchar2(20),sal number,job char(10));
现在插入数据:-
SQL>insert into tablename values(&eid,'&ename',&sal,'&job');
检查此链接 http://www.dba-oracle.com/t_optimize_insert_sql_performance.htm
这是我对快速插入的建议。
触发器 - 禁用与表关联的任何触发器。插入完成后启用。
索引 - 删除索引并在插入完成后重新创建它。
陈旧的统计信息 - 重新分析表和索引统计信息。
索引碎片整理 - 如果需要,重建索引 使用无日志记录 - 使用 INSERT APPEND 插入(仅限 Oracle)。这种方法是非常危险的方法,不会生成重做日志,因此您不能进行回滚 - 在开始之前备份表并且不要尝试实时表。检查您的数据库是否有类似的选项
并行插入:运行并行插入将更快地完成工作。
使用批量插入约束 - 插入期间开销不大,但仍然是检查的好主意,即使在第 1 步之后它仍然很慢
您可以在http://www.dbarepublic.com/2014/04/slow-insert.html了解更多信息
也许您最好的选择之一是实际上尽可能避免使用 Oracle。我自己对此感到困惑,但 Java 进程通常可以胜过许多使用 OCI(阅读:SQL Plus)或会占用您大量时间来正确处理的 Oracle 实用程序(阅读:SQL*Loader )。
这也不会阻止您使用特定的提示(例如 / APPEND /)。
每次我转向这种解决方案时,我都会感到惊喜。
干杯,
罗洛