关于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_normalfrom 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_normalfrom 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 fromdual;

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