关于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全部阻塞。