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