Oracle insert /*+ APPEND */原理解析

关于insert /*+ append */我们需要注意以下三点: a、非归档模式下,只需append就能大量减少redo的产生;归档模式下,只有append+nologging才能大量减少redo。 b、insert /*+ append */时会对表加锁(排它锁),会阻塞表上的除了select以外所有DML语句;传统

关于insert /*+ append */我们需要注意以下三点:

a、非归档模式下,只需append就能大量减少redo的产生;归档模式下,只有append+nologging才能大量减少redo。
b、insert /*+ append */ 时会对表加锁(排它锁),会阻塞表上的除了select以外所有DML语句;传统的DML在TM enqueue上使用模式3(row exclusive),其允许其他DML在相同的模式上获得TM enqueue。但是直接路径加载在TM enqueue使用模式6(exclusive),这使其他DML在直接路径加载期间将被阻塞。
c、insert /*+ append */ 直接路径加载,速度比常规加载方式快。因为是从HWM的位置开始插入,也许会造成空间浪费。

1.环境介绍

数据库版本:

1
2
3
4
5
6
7
8
SQL>  select  from  v$version;
BANNER
---------------------------------------------------------------------
Oracle  Database  11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS  for  Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

网上说测试时不要使用auto trace来查看redo size,这个值是有偏差的.建议建立一个视图:

1
2
3
4
5
6
SQL>  create  or  replace  view  redo_size  as
select  value
from  v$mystat, v$statname
where  v$mystat.statistic# = v$statname.statistic#
and  v$statname. name  'redo size' ;
-- 视图已创建。

2.示例演示:

2.1 非归档模式

1
2
3
4
5
6
SQL> archive log list
数据库日志模式             非存档模式
自动存档             禁用
存档终点            USE_DB_RECOVERY_FILE_DEST
最早的联机日志序列     95
当前日志序列           97

2.1.1 nologging表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SQL>  create  table  test1 nologging  as  select  from  dba_objects  where  1=0;
表已创建。
  
SQL>  select  from  redo_size;
      VALUE
----------
   25714940
  
SQL>  insert  into  test1  select  from  dba_objects;
已创建72753行。
  
SQL>  select  from  redo_size;
      VALUE
----------
   34216916
  
SQL>  insert  /*+ APPEND */   into  test1  select  from  dba_objects;
已创建72753行。
  
SQL>  select  from  redo_size;
      VALUE
----------
   34231736
  
SQL>  select  (34231736-34216916) redo_append , (34216916-25714940) redo_normal from  dual;
REDO_APPEND REDO_NORMAL
----------- -----------
       14820     8501976

2.1.2 logging表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
SQL>  create  table  test2  as  select  from  dba_objects  where  1=0;
  
表已创建。
  
SQL>  select  from  redo_size;
      VALUE
----------
   34273348
  
SQL>  insert  into  test2  select  from  dba_objects;
  
已创建72754行。
  
SQL>  select  from  redo_size;
      VALUE
----------
   42775336
  
SQL>  insert  /*+ APPEND */   into  test2  select  from  dba_objects;
已创建72754行。
  
SQL>  select  from  redo_size;
      VALUE
----------
   42790156
  
SQL>  select  (42790156-42775336) redo_append , (42775336-34273348) redo_normal from  dual;
REDO_APPEND REDO_NORMAL
----------- -----------
       14820     8501988

2.2归档模式下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SQL> shutdown immediate
数据库已经关闭。
已经卸载数据库。
ORACLE例程已经关闭。
SQL> startup mount
ORACLE例程已经启动。
  
Total System  Global  Area  477073408 bytes
Fixed  Size                   1337324 bytes
Variable  Size              293603348 bytes
Database  Buffers          176160768 bytes
Redo Buffers                5971968 bytes
数据库装载完毕。
SQL>  alter  database  archivelog;
数据库已更改。
  
SQL>  alter  database  open ;
数据库已更改。
  
SQL> archive log list
数据库日志模式            存档模式
自动存档             启用
存档终点            USE_DB_RECOVERY_FILE_DEST
最早的联机日志序列     95
下一个存档日志序列   97
当前日志序列           97

2.2.1 nologging表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
SQL>  select  from  redo_size;
     VALUE
----------
      17936
  
SQL>  insert  into  test1  select  from  dba_objects;
已创建72754行。
  
SQL>  select  from  redo_size;
      VALUE
----------
    8490972
  
SQL>  insert  /*+ APPEND */   into  test1  select  from  dba_objects;
已创建72754行。
  
SQL>  select  from  redo_size;
      VALUE
----------
    8506164
  
SQL>  select  (8506164-8490972) redo_append , (8490972-17936) redo_normal  from dual;
REDO_APPEND REDO_NORMAL
----------- -----------
       15192     8473036

2.2.2 logging表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
SQL>  select  from  redo_size;
      VALUE
----------
    8506780
  
SQL>  insert  into  test2  select  from  dba_objects;
已创建72754行。
  
SQL>  select  from  redo_size;
      VALUE
----------
   16979516
  
SQL>  insert  /*+ APPEND */   into  test2  select  from  dba_objects;
已创建72754行。
  
SQL>  select  from  redo_size;
      VALUE
----------
   25518172
  
SQL>  select  (25518172-16979516) redo_append , (16979516-8506780) redo_normal from  dual;
REDO_APPEND REDO_NORMAL
----------- -----------
     8538656     8472736

在归档模式下,对于常规表的insert append产生和insert同样的redo
此时的insert append实际上并不会有性能提高.
但是此时的append是生效了的。

3.insert /*+ append */会阻塞除select以外的DML语句,direct-path insert操作是单独一个事务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
SQL>  select  count (*)  from  test2;
   COUNT (*)
----------
     291016
  
SQL>  insert  into  test2  select  from  dba_objects;
已创建72754行。
  
SQL>  select  count (*)  from  test2;
   COUNT (*)
----------
     363770
  
SQL>  insert  /*+ APPEND */  into  test2  select  from  dba_objects;
已创建72754行
  
同一个session下:
  
SQL>  select  count (*)  from  test2;
select  count (*)  from  test2
*
第 1 行出现错误:
ORA-12838: 无法在并行模式下修改之后读/修改对象
  
SQL>  commit ;
提交完成。
  
SQL>  select  count (*)  from  test2;
   COUNT (*)
----------
     436524
  
SQL>  insert  /*+ APPEND */  into  test2  select  from  dba_objects;
已创建72754行。
  
SQL> shutdown immediate
ORA-01097: 无法在事务处理过程中关闭 - 请首先提交或回退
  
SQL>  select   from  v$mystat  where  rownum<2;
  
        SID STATISTIC#      VALUE
  
---------- ---------- ----------
  
        224          0          1
  
SQL>  select  KADDR,TYPE,LMODE  from  v$lock  where  sid=224;
  
KADDR            TY      LMODE
---------------- -- ----------
0000000071BAE180 TM          6
0000000070CB11B8 TX          6

另外开启一个会话,就会发现只能select,其他DML全部阻塞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值