SQL*Loader是Oracle数据库自带的一款命令行批量数据加载工具,主要用于将外部平面文件中的大量记录高效导入数据库表。它通过解析控制文件中定义的格式规则,读取数据文件并逐行转换为INSERT操作或直接路径数据块写入。与手工编写存储过程逐条插入相比,SQL*Loader在初始化数据仓库、迁移历史数据、定期同步外部系统文本文件等场景下具有明显优势,特别是面对百万行以上数据量时,性能差距可达数十倍。

一、SQL*Loader的核心组成与基本执行流程
一次完整的SQL*Loader作业通常涉及四类文件:可执行程序sqlldr、控制文件、数据文件以及运行后产生的日志文件、坏记录文件和废弃记录文件。控制文件是整个装载过程的核心,它使用Oracle特有的语法描述数据文件的位置、记录格式、目标表结构以及字段之间的映射关系。数据文件可以是固定长度格式,也可以是逗号、制表符等定界符分隔的可变格式,甚至可以是二进制流。
执行时,sqlldr会先读取控制文件,将其转换为内部解析规则,再按照规则逐行扫描数据文件。每条记录根据字段定义拆分成若干列,随后生成相应的绑定变量数组提交给数据库。如果某条记录因字段数量不匹配、数据类型转换失败或违反约束而无法入库,该记录会被写入坏记录文件,同时写入日志文件供后续排查。被DISCARD条件过滤掉的记录则进入废弃文件,三种文件的扩展名通常分别为.log、.bad和.dsc。
命令行调用方式非常简单,下面是一个典型示例。其中userid用于指定连接信息,control指定控制文件路径,log、bad、discard分别指定输出文件位置。如果不显式指定,SQL*Loader会自动以控制文件名为基础生成相应文件。
sqlldr userid=scott/tiger@orcl control=/home/oracle/load/employees.ctl log=/home/oracle/load/employees.log bad=/home/oracle/load/employees.bad discard=/home/oracle/load/employees.dsc
运行结束后,可以通过日志文件中的统计信息快速判断加载结果,包括成功加载的行数、因错误跳过的行数、因过滤条件废弃的行数以及总耗时。这些信息对后续调优和问题定位非常关键。
二、控制文件编写:字段映射与格式处理
控制文件的语法结构通常以LOAD DATA开头,接着通过INFILE指定数据文件路径,然后使用INTO TABLE声明目标表。字段分隔符通过FIELDS TERMINATED BY指定,可选OPTIONALLY ENCLOSED BY处理带引号的字段。TRAILING NULLCOLS是一个非常实用的子句,它允许记录末尾缺失的列自动填充为NULL,避免因数据文件末尾字段为空而导致整行被丢弃。
下面是一个加载员工信息的控制文件示例。数据文件为CSV格式,第一行是标题需要跳过,因此使用OPTIONS (SKIP=1)。字段列表按顺序与表列对应,其中hiredate列使用DATE关键字指定了输入日期格式,这样SQL*Loader会按照YYYY-MM-DD解析字符串并转换为日期类型。
OPTIONS (SKIP=1) LOAD DATA INFILE '/home/oracle/load/employees.csv' BADFILE '/home/oracle/load/employees.bad' DISCARDFILE '/home/oracle/load/employees.dsc' APPEND INTO TABLE employees FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' TRAILING NULLCOLS ( empno, ename, hiredate DATE 'YYYY-MM-DD', sal, deptno )
如果数据文件是固定宽度格式,则需要使用POSITION(start:end)语法来明确每一列的起止位置。例如empno POSITION(1:6)表示取每行第1到第6个字符作为员工编号。固定宽度格式没有分隔符,因此不需要FIELDS TERMINATED BY子句,而是直接在每个字段内部使用POSITION限定。这种方式在对接银行、电信等行业的传统文本接口时非常常见。
对于某些需要转换或过滤的字段,可以在字段列表中直接使用SQL函数或SQL*Loader提供的特殊操作。例如NULLIF col=BLANKS表示当该列为空格时插入NULL值,DECODE函数可以把编码值转换为可读字符串。SEQUENCE(MAX,1)可以给自增列自动生成递增序号,而CONSTANT关键字则能为所有行写入同一个常量值。这些能力使控制文件不仅能完成简单的列映射,还能承担一部分轻量级的数据清洗工作。
三、加载模式选择:常规路径与直接路径
SQL*Loader支持两种主要加载模式:常规路径加载和直接路径加载。常规路径加载使用标准的SQL INSERT语句,通过数据库缓冲区逐行插入数据。这种方式会完整地记录重做日志,触发所有BEFORE和AFTER行级触发器,维护所有索引和约束。它的优点是行为与普通INSERT完全一致,适用于数据量不大、需要严格遵循业务规则或数据中大量违反约束的场景。
直接路径加载则绕过SQL处理引擎,将数据直接格式化为Oracle数据块写入数据文件。它只记录必要的空间管理日志,默认不触发DML触发器,不维护除主键和唯一约束之外的索引,因此性能远高于常规路径。要启用直接路径,只需在命令行或控制文件选项中添加direct=true。下面是一个并行直接路径加载的示例,同时使用parallel=true允许多个sqlldr进程同时向同一个表写入。
sqlldr userid=scott/tiger@orcl control=/home/oracle/load/employees.ctl direct=true parallel=true
直接路径加载虽然速度快,但也有一定限制。例如目标表上如果有启用状态的引用约束、BITMAP索引或某些类型的触发器,直接路径加载可能会失败或自动降级为常规路径。加载过程中表会被锁定,其他事务无法进行DML操作。因此在选择直接路径前,建议先评估表结构、索引数量以及是否需要保留业务规则。对于一次性初始化或数据仓库批量刷新,直接路径通常是最优选择;而对于需要严格触发审计触发器或级联更新的在线业务表,则应使用常规路径。
四、性能调优关键参数与实战建议
SQL*Loader的性能受多个缓冲区参数影响。ROWS参数控制一次提交的行数,常规路径下默认值为64。适当增大ROWS可以减少提交次数,降低日志切换压力,建议设置为5000到10000之间。BINDSIZE指定绑定数组的最大字节数,默认只有256KB,对于宽表或大批量加载往往不够,建议提高到10MB甚至更高。READSIZE和STREAMSIZE分别控制读取缓冲区大小和直接路径流缓冲区大小,增大这两个值能显著提升文件IO效率。
以下控制文件片段展示了如何通过OPTIONS子句集中设置这些参数。需要注意的是,这些参数应在控制文件开头声明,并且值的大小要结合数据库SGA和目标表结构合理配置,并非越大越好。过大的缓冲区可能导致内存换页,反而降低吞吐量。
OPTIONS (ROWS=10000, BINDSIZE=10485760, READSIZE=1048576, STREAMSIZE=1048576) LOAD DATA INFILE '/home/oracle/load/large_data.csv' INTO TABLE sales_fact FIELDS TERMINATED BY '|' TRAILING NULLCOLS ( order_id, product_id, quantity, amount, order_date DATE 'YYYY-MM-DD HH24:MI:SS' )
对于超大文件,除了调大缓冲区,还可以考虑使用并行加载。并行加载的常用方式是将数据文件按逻辑或物理拆分,然后启动多个sqlldr进程,每个进程加载一个子文件,并在命令行中指定parallel=true。如果目标表是分区表,还可以按分区键拆分数据文件,使每个进程只加载特定分区,进一步提升并行效率。需要注意的是,并行直接路径加载要求目标表没有全局索引,或者索引在加载前先删除、加载完成后重建。
五、日志分析与错误定位
SQL*Loader运行完成后,日志文件是排查问题的第一手资料。日志中不仅包含加载统计信息,还会详细列出每条失败记录的错误原因,例如数据长度超过列定义、日期格式不匹配、违反非空约束等。通过定位ORA-错误编号,可以快速判断问题类型。对于少量错误,通常的做法是允许加载继续进行,事后再单独处理坏记录文件中的问题行。
控制文件中的ERRORS参数用来设置允许的最大错误行数,默认值为50。如果加载过程中错误行数超过该阈值,SQL*Loader会中止作业。在初始加载陌生数据源时,可以将ERRORS设置得较大,例如1000或更多,以便一次性发现所有格式问题。坏记录文件保存了原始数据行,可以直接打开检查,或者清洗后重新装载。
OPTIONS (ERRORS=200) LOAD DATA INFILE '/home/oracle/load/employees.csv' BADFILE '/home/oracle/load/employees.bad' DISCARDFILE '/home/oracle/load/employees.dsc' INTO TABLE employees FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' TRAILING NULLCOLS ( empno, ename, hiredate DATE 'YYYY-MM-DD', sal, deptno )
除了错误行数控制,TRAILING NULLCOLS的缺失也是常见的加载失败原因。很多CSV文件最后一列可能为空,如果控制文件没有声明该子句,SQL*Loader会认为字段数量不足,导致部分记录被错误丢弃。另一个常见问题是定界符选择不当,数据字段本身包含了与分隔符相同的字符,此时必须使用OPTIONALLY ENCLOSED BY来包裹字段,或者更换更不常见的分隔符,例如管道符|。理解这些文件格式细节,能够显著减少加载过程中的无效重试。
总体来看,掌握SQL*Loader的关键在于控制文件编写、路径模式选择以及参数调优三个层面。结合实际数据文件格式和业务约束,选择合适的加载策略,可以在保证数据质量的同时大幅提升批量数据入库效率。
Oracle SQL*Loader批量数据加载控制文件修改时间:2026-08-20 21:11:47