ORACLE使用/*+append*/直接路径加载插入需要注意的问题


 在进行大量数据加载时,常使用append进行insert叫做直接路径加载插入,使用这种提示因为系统不去查找freelist链表中的空闲块,直接在高水标记位(HWM)以上插入数据,因此加载速度比较快。append 属于direct insert,归档模式下append + table nologging会大量减少日志,非归档模式append会大量减少日志,append方式插入只会产生很少的undo数据。

但是也应该注意直接路径加载插入有一些不同:


1.它不记录日志,因此一旦插入的数据在没有保存回磁盘的时候发生掉电之类的状况插入的数据不能重做。


2.它比较浪费磁盘空间,有心的同学可以做个简单的实验,创建个空表,用insert 插一些数据,然后delete掉,然后再用insert 插一些数据,再delete掉,这样反复操作,最终用delete把表清空,然后用下面的语句查一下表的大小,可以看到一个空表占了可怕的磁盘空间!

Select round(Sum(bytes)/1024,2)||‘KB’ as sizes 

From dba_extents

where segment_name='表名'

Group By owner,segment_name,segment_type;


3.它在不同的Oracle版本中所加的锁是不一样的,我在两个版本中做了实验。

在Oracle Database 10g Enterprise Edition Release 10.2.0.1.0中,如果插入操作的语法是

insert into XXX values(XXX);

那么系统加的是row exclusive锁,也就是正常insert所加的行级锁,但是如果插入操作的语法是

insert into XXX select XXX from XXX;

那么系统加的是exclusive锁,相当于表级锁,加表级锁意味着在本会话没有commit的时候其他任何会话都不能再进行insert,update,delete操作。不过这里看起来更严重,就连自己的会话也不能再进行任何insert,update,delete操作,否则就会提示:

ETL@RACTEST> insert into ljntest select a from ljntest2;


1 row created.


Elapsed: 00:00:00.01

ETL@RACTEST> insert into ljntest select a from ljntest2;

insert into ljntest select a from ljntest2

*

ERROR at line 1:

ORA-12838: cannot read/modify an object after modifying it in parallel

在Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 中就简单一些了,不管是哪种语法,一概加的是exclusive锁!


4.如果表上有索引,将会产生索引的回滚信息,而且索引的块会被读进buffer cache ,所以如果使用直接路径方式向表中传送大量数据,可先将表上的索引删掉,插入结束后,再重新建立索引 。


请使用浏览器的分享功能分享到微信等