以前一直没注意sql loader用direct方式时怎么处理索引的,也是因为一般用sql loader都是往临时表里导数据,用不着索引。今天试了一下,才发现direct=true时索引不是在insert时维护的,而是在把数据全部插入后再去维护。
以下是实验
设 SQLLDR表上字段 ID建立了PK PK_SQLLDR,相应的索引为UK_SQLLDR
表中已经有了一条ID=0的记录,sqlldr的ctl文件采用append方式
===================================================
不采用direct方式时>sqlldr aeowner/aeowner@jinlo control=sqlldr.1.ctl
log中显示这条记录没有被插入
记录 1: 被拒绝 - 表 SQLLDR 出现错误。
ORA-00001: 违反唯一约束条件 (AEOWNER.PK_SQLLDR)
看一下,确实没有插入
select count(0) from SQLLDR where id=0;
COUNT(0)
----------
1
=====================================================
采用direct方式时>sqlldr aeowner/aeowner@jinlo control=sqlldr.1.ctl direct=true
log中没有异常记录
这条记录确实被插入了
SQL> select count(0) from SQLLDR where id=0;
COUNT(0)
----------
2
相应的索引也处于不可用状态
SQL> select status from dba_indexes where table_name='SQLLDR' and index_name='PK_SQLLDR';
STATUS
--------
UNUSABLE
并且,由于建立了主键,整个表上的写操作都无法进行
SQL> delete from sqlldr where id=0;
delete from sqlldr where id=0
ORA-01502: 索引 'AEOWNER.PK_SQLLDR' 或这类索引的分区处于不可用状态
insert into sqlldr (id) values (1);
insert into sqlldr (id) values (1)
ORA-01502: 索引 'AEOWNER.PK_SQLLDR' 或这类索引的分区处于不可用状态
=====================================================
以上实验可知,对于目标表上有约束(唯一索引)的情况,direct方式可能会破坏数据的完整性,甚至使得后续操作无法继续进行。因此
1) 不是出于性能考虑的话,不要采用direct方式
2) 如果采用direct方式,检查结果时,不能只看sqlldr的log中,还要检查目标表上唯一索引的status,以防悄悄地引入错误数据