在过去的几天里,我一直在使用 Oracle 的 SQL*Loader 尝试将数据批量加载到 Oracle 中。在尝试了不同的选项组合后,我惊讶地发现传统路径加载比直接路径加载运行得快得多。
关于这个问题的一些事实:
- 要加载的记录数为 60K。
- 加载前目标表中的记录数为 7 亿。
- Oracle 版本是 11g r2。
- 数据文件包含日期、字符(ascii,无需转换)、整数、浮点数。没有斑点/斑点。
- 表按哈希分区。散列函数与 PK 相同。
- 表的并行设置为 4,而服务器有 16 个 CPU。
- 索引是本地分区的。索引的平行度(来自 ALL_INDEXES)为 1。
- 目标表上只有 1 个 PK 和 1 个索引。使用索引构建的 PK 约束。
- 检查索引分区显示分区之间的记录分布非常均匀。
- 数据文件是分隔的。
- 使用了 APPEND 选项。
- 通过 SQL 选择和删除加载的数据非常快,几乎是即时响应。
使用传统路径,加载在大约 6 秒内完成。
使用直接路径加载,加载大约需要 20 分钟。最糟糕的运行需要 1.5 小时才能完成,但服务器根本不忙。
如果启用了 skip_index_maintenance,则直接路径加载将在 2-3 秒内完成。
我尝试了很多选项,但没有一个能带来明显的改进……不可恢复、已排序索引、多线程(我在多 CPU 服务器上运行 SQL*Loader)。他们都没有改善这种情况。
这是我在 SQL*Loader 以直接模式运行期间一直看到的等待事件:
- 事件:db 文件顺序读取
- P1/2/3:文件#、块#、块(从 dba_extents 检查它是一个索引块)
- 等待类:用户 I/O
有谁知道直接路径加载出了什么问题?或者有什么我可以进一步检查以真正挖掘问题的根本原因吗?提前致谢。