Append与Direct-Path Insert(一)
来源:互联网 发布:2016中国移动网络电视 编辑:程序博客网 时间:2024/05/17 22:54
Append提示在进行批量数据加载的时候,是很高效的一个手段。前段进行实验,发现这个hint在使用的时候,还是有一些需要注意的地方的。
1、 基础知识
还是先看看基础知识吧。append是oracle提供给SQL开发者使用的hint之一。所谓hint的作用,简单说就是影响Oracle优化器生成特定的执行计划。SQL是一种数据描述语言。实际对数据进行操作是通过对SQL的解析,生成执行计划的过程。
Append提示的作用提示优化器使用直接路径插入(Direct-Path Insert)方式。下面简单说下Oracle的两种插入和两种模式。
两种工作模式,分别成为串行化模式(Serial Mode)和并行模式(Parallel Mode)。串行化模式就是我们通常的SQL工作模式,一个SQL操作内部顺序执行。并行模式就会将工作按照一定规则划分为多个工作线程同时执行,之后汇合结果。在进行大数据量操作的时候,可以考虑采用并行模式以提高效率。
插入方式上,Oralce有Conventional Insert和Direct-Path Insert两种。
传统插入(Conventional Insert)方式是我们通常使用的Insert方式。默认情况下,传统插入是使用串行化模式的。在串行化模式下,如果在insert中使用append提示,Oracle会对该条insert使用Direct-Path插入方式。
直接路径(Direct-Path)方式在是并行操作模式下的默认插入方式。在并行模式下,只有使用noappend提示,才能使用传统的插入方式。
所以,插入操作的时候,究竟是使用并行还是串行模式,与append提示无关。
在使用直接路径插入的时候,数据并不是先从数据表中找到随机的空位后插入,而是直接将数据插入到数据表的末尾,直接推高高水位线。这种操作方式,较传统的方式要快。
2、 快速的直接路径插入
相对于传统模式,使用append提示之后,批量插入的速度可以得到显著的提升。
SQL> create table t as select * from dba_objects where 1=0;
Table created
SQL> select count(*) from t;
COUNT(*)
----------
0
Executed in 0.01 seconds
//一般插入方式
SQL> insert into t select * from dba_objects;
50367 rows inserted
Executed in 0.571 seconds
//还原环境,删除数据
SQL> truncate table t;
Table truncated
Executed in 0.431 seconds
//Append插入方式
SQL> insert /*+ append */into t select * from dba_objects;
50367 rows inserted
Executed in 0.45 seconds
通过上面的简单实验,可以看到:在相同的条件下,使用append进行数据表的插入,要显著的快于传统方式。这种特点在海量数据加载、迁移的过程中,可以显著的提高效率。要注意,这种方式因为直接提升高水位线,不会利用表中原有被删除的空间,在一些删除操作比较多的表中,会造成很大的空间浪费,要避免滥用引发空间膨胀问题。
3、 Append操作与锁
在使用Append操作时,要注意Append操作是一种特殊的插入操作,会阻止包括自身会话在内的插入操作。首先,我们先看一下普通插入的系统行为。
//数据准备,建立数据表
SQL> create table t as select owner, object_id, rownum num from dba_objects where 1=0;
Table created
//session1中,启动一个插入操作
SQL> insert into t select owner,object_id,rownum from dba_objects where rownum<10;
9 rows inserted
SQL> select * from v$mystat where rownum<2;
SID STATISTIC# VALUE
---------- ---------- ----------
140 0 1
//观察系统中锁的情况
SQL> select * from v$lock where sid=140;
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
6BDC4074 6BDC408C 140 TM 53083 0 3 0
6BE3BE7C 6BE3BF98 140 TX 458760 692 6 0
说明:Session1(SID=140)首先在数据表对象加上一个TM锁,模式为3共享锁,同时对其插入的数据项加了事务TX锁,模式为6独占锁;
//启动另一个session2,执行插入操作
SQL> insert into t select owner, object_id, rownum from dba_objects where object_id=120;
1 row inserted
SQL> select sid from v$mystat where rownum<2;
SID
----------
142
SQL> select * from v$lock where sid in (140,142);
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
6BDC4074 6BDC408C 140 TM 53083 0 3 0
6BDC4138 6BDC4150 142 TM 53083 0 3 0
6BE127B8 6BE128D4 142 TX 655371 658 6 0
6BE3BE7C 6BE3BF98 140 TX 458760 692 6 0
说明:session2(SID=142)进行插入操作,也尝试在对象表(ID1 53083)上加一个共享锁TM,LMODE=3。与Session1(SID=140)的TM锁可以共存(共享锁之间),同时将插入事务锁TX,类型为独占锁,与原有的session1独占锁加上的是不一样的对象。
说明:在传统的插入操作中,会话之间插入操作是不会相互影响的。同一个事务内部,进行插入操作之间,也没有互斥的情况。
下面我们开始实验append提示。(下面实验是使用相同的两个session(sid=140,142))。
//在session1(sid=140)中使用append关键字插入。
SQL> insert /*+ append */ into t select owner, object_id, rownum from dba_objects where rownum<10;
9 rows inserted
//同一个session内,进行相同的操作
SQL> insert /*+ append */ into t select owner, object_id, rownum from dba_objects where rownum<10;
ORA-12838: 无法在并行模式下修改之后读/修改对象
说明:即使在同一个session里,对一个表进行append插入之后,必须先commit之后,才能进行相同表的操作。这个特点可能与append采用的并行模式操作有关。
这个时候,我们查看一下当前sesson1(sid=140)的锁状态。
//查看session1的锁状况
SQL> select * from v$lock where sid=140;
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
6BDC4074 6BDC408C 140 TM 53083 0 6 0
6BE3BE7C 6BE3BF98 140 TX 196611 652 6 0
请注意:当我们进行append操作的时候,oracle对表t加锁状况出现差异。变化点在数据表锁TM的模式LMODE为6(排他锁),这点与一般插入存在差异。TM模式6的现象说明,在进行append操作的时候,oracle对数据表级的锁操作不是一个共享锁(LMODE=3),而是一个排他锁(LMODE=6)。从锁知识角度,如果这时其他会话尝试插入操作(向数据表T加一个LMODE=3的共享锁),是会被hange住。
//此时session2(sid=142)
SQL> select sid from v$mystat where rownum<2;
SID
----------
142
//尝试以一个一般方式插入数据
SQL> insert into t select owner, object_id, rownum from dba_objects where object_id=120;
//session2被hange住
//此时查看两个会话的锁状况
SQL> select * from v$lock where sid in (140,142);
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
6BDC4074 6BDC408C 140 TM 53083 0 6 0
6BDC4138 6BDC4150 142 TM 53083 0 0 3
6BE3BE7C 6BE3BF98 140 TX 196611 652 6 0
说明:此时session2尝试在表T上加入一个共享锁Lmode=3,因为已经被sid=140独占排他。所以被hange住。
//session1 commit之后。
SQL> commit;
Commit complete
//session2解除hange状态
结论:实验结果和我们预想的一样。共享锁和排他锁是不能兼容的。通常,当我们在一个会话中使用了append一批数据后,其他会话是不能插入操作。如果进行的话,会被hange住。进行append操作的会话,也不能在表中进行其他操作。除非提交或回滚事务。
作为这个结论的拓展实验,我们进行下列尝试。
//在session1已经进行append的操作情况下
//如果session2也要求进行append的操作时候
SQL> insert /*+ append */ into t select owner, object_id, rownum from dba_objects where rownum<10;
//session2也hange住
SQL> select * from v$lock where sid in (140,142);
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
6BDC4074 6BDC408C 140 TM 53083 0 6 0
6BDC4138 6BDC4150 142 TM 53083 0 0 6
6BE3BE7C 6BE3BF98 140 TX 65571 638 6 0
//sesion2 被hange住
结论一致,区别在于session2在进行append的操作的时候,也会尝试获取排他的表锁,自然也会被hange住。
综上所述:append操作是一种有并行操作趋势的快速插入hint。在使用的时候,要注意及时的commit,以防止出现严重的并发操作问题。同时,在高并发的系统(OLTP)中,也要注意慎用。
那么,是不是append都是要获取排他锁呢?排他锁和共享锁之间关系如何协同?还有在同一个会话中,对锁控制有什么特点?我们在下一篇中继续探讨。
- Append与Direct-Path Insert(一)
- Append与Direct-Path Insert(二)
- Direct Path Insert与APPEND, PARALLEL的梳理与小结
- Direct Path Insert与APPEND, PARALLEL的梳理与小结
- direct path insert 以及append参数
- Direct Path Insert - APPEND HINT and TM Enqueue LOCK Behaviour
- Direct Path Insert与 enq:TM
- Direct Path Insert - APPEND HINT and TM Enqueue LOCK Behaviour (文档 ID 1317447.1)
- Direct-Path Insert 直接路径加载
- Oracle Direct-Path Insert学习笔记
- Direct-Path INSERT(直接路径插入)
- 用直接路径(direct-path)insert提升性能的两种方法
- 用直接路径(direct-path)insert提升性能的两种方法
- Direct-Path Insert 直接路径加载,有没有必要,为什么
- insert /*+append */
- insert /*+ APPEND */
- insert /*+ APPEND */
- insert /*+append*/
- ubuntu 修改时区
- 管理路由器每次要输密码真是麻烦,自己来写个浏览器
- linux下的ln命令
- VC学习: CPoint,CSize,CRect类说明
- Oracle 10g Scheduler 特性
- Append与Direct-Path Insert(一)
- C++中的虚函数(virtual function)
- 李某某判10年我觉得不够呀
- Linux下Mysql的配置管理
- Append与Direct-Path Insert(二)
- 禁止Solaris系统不必要的网络服务
- 适配iOS7开发
- tp_link无线路由器设置(上海大学宿舍)
- 王力宏竟然不是和刘亦菲在一起