Oracle数据泵导入大表卡在LOADING是因直接路径触发索引/约束维护,建议禁用约束、排除索引重建、手动分步处理,并优先用外部表+APPEND提升批量加载性能。

Oracle数据泵导入大表时卡在“LOADING”状态
数据泵 impdp 导入超千万行表时,常卡在 LOADING 阶段十几分钟不动,不是挂了,是默认启用了直接路径(direct_path)但触发了大量索引维护和约束检查。尤其当目标表有多个非空约束、外键或函数索引时,性能断崖式下跌。
实操建议:
- 导入前用
ALTER TABLE ... DISABLE CONSTRAINT ALL临时禁用约束(注意记录哪些被禁,后续要手动启用) - 加参数
exclude=INDEX,CONSTRAINT跳过索引和约束创建,导入完再用CREATE INDEX和ALTER TABLE ... ENABLE CONSTRAINT分步重建 - 确认是否真需要直接路径:如果表有
LOB字段或触发器,direct_path会自动退化为外部表模式,此时加access_method=external_table反而更可控 - 避免用
REMAP_SCHEMA同时改 schema 和建索引——这会让数据泵在加载数据时反复查字典视图,拖慢进度
用外部表替代 INSERT … SELECT 做批量加载
想把 CSV 或 Oracle 目录下的文本文件快速灌进表里?别写 PL/SQL 循环读行再 INSERT,那是百行/秒级;用外部表 + INSERT /*+ APPEND */ 能到十万行/秒以上,前提是文件格式干净、字段对齐、无乱码。
实操建议:
- 先建目录对象:
CREATE DIRECTORY ext_dir AS '/u01/data',并授READ权给用户 - 外部表定义里必须显式指定
REJECT LIMIT UNLIMITED,否则一行格式错就全盘失败 - 字符集要对齐:若源文件是 UTF-8,外部表的
CHARACTERSET UTF8缺一不可,否则中文变??? - 不要在外部表上建索引或约束——它只是个“视窗”,所有校验得靠导入后的主表承担
impdp 进度不更新,但 v$session_longops 显示 0%
v$session_longops 里看到 OPNAME = 'Loader' 且 sofar = 0,不代表没干活。这是数据泵在预处理阶段(解析元数据、分配区、检查空间),尤其当 TABLE_EXISTS_ACTION=TRUNCATE 且表上有大索引时,truncate 本身就会锁表并等待回滚段清理,耗时可能远超实际加载。
实操建议:
- 导入前手动
TRUNCATE TABLE并ALTER SYSTEM CHECKPOINT,让 impdp 跳过 truncate 步骤 - 监控
v$lock和v$transaction,确认有没有长事务阻塞 truncate - 用
LOGTIME=ALL参数启动 impdp,日志里每一步耗时都打出来,比看进度条靠谱得多 - 别信
STATUS命令返回的“Completed”,它只表示作业调度完成,不保证数据已刷盘——查dba_segments的blocks增长才真实
大数据量下外部表 vs 数据泵的选择边界
不是越大越该用数据泵。当单次导入数据超过 50GB、且源库和目标库版本差异大(比如从 11g 导到 19c),外部表反而更稳:数据泵依赖导出时的兼容性设置(VERSION 参数),一旦设错,ORA-39142 报错后只能重来;外部表则完全绕过元数据转换,纯靠 SQL 层解析。
实操建议:
- 若需跨版本迁移,优先选外部表 +
INSERT /*+ APPEND NOLOGGING */,但记得提前ALTER DATABASE NOARCHIVELOG或确保归档空间充足 - 数据泵适合“整库/整 Schema 备份恢复”,外部表适合“按业务模块分批灌数”,后者更容易做失败重试
- 外部表无法处理
DATE字段的时区隐式转换,TO_DATE必须显式写在INSERT语句里,否则ORA-01843甩脸就来
真正卡住的从来不是工具选错,而是没想清楚“这一批数据,到底要不要立刻可查询”。要立刻可用,就得接受索引延迟;能容忍几小时只读窗口,就该关约束、关日志、分步建索引。这些取舍,比敲哪个命令重要得多。










