Oracle提供两种类型的插入语句:常规插入和直接路径插入
Oracle提供两种类型的插入语句:常规插入(conventional insert)和直接路径插入(direct-path insert),直接路径插入的目的是为了高效地加载大量的数据,它以牺牲部分功能为代价,因此受到很多的限制。
1. 直接路径加载的性能
直 接路径加载把数据直接插入到要修改的段的高水位(HWM)以上,从而生成了最少量的undo(只生成数据字典的undo,不生成块中数据的undo),且 不通过高速缓存,因此它的性能比常规插入要好。如果性能是首要目标,还可以考虑配合使用最小日志模式(nologging)。
2. 直接路径加载的限制
1)一张表同时只能有一个直接路径插入,因此不适合小数据量的插入,只适合大批量的数据加载;
2)在HWM下的空闲空间不会被利用;
3)一张表在做直接路径插入的同时,同一会话不能对其做任何操作(select都不可以);
4)只有insert inot ... select ... 语句、merge语句和使用OCI直接路径接口的应用程序才可以使用。
3. 直接路径加载的使用方法
1)在SQL语句中加append提升;
2)并行地执行SQL语句。
4. ORA-12938错误
如果直接路径加载的事务未提交或回滚,则同一个会话无法访问被修改的表(报ORA-12838: cannot read/modify an object after modifying it in parallel),非同一个会话可以访问。
实验如下:
SQL>insert /*+ append */ into test select * from test;
24872 rows created.
SQL>select count(*) from test;
select count(*) from test
*
ERROR at line 1:
ORA-12838: cannot read/modify an object after modifying it in parallel
SQL>commit;
Commit complete.
SQL>select count(*) from test;
COUNT(*)
----------
49744
使用append提示进行insert叫做直接路径加载插入,使用这种提示因为系统不去查找freelist链表中的空闲块,直接在高水标记位以上插入数据,因此速度比较快。但是也应该注意直接路径加载插入有一些不同:
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锁!
所以大家在使用直接路径加载插入时或是测试开发的代码时一定要注意这三点。
posted on 2014-07-14 23:13 pengdaijun 阅读(1243) 评论(0) 编辑 收藏 举报