当需要对一个非常大的表INSERT的时候,会消耗非常多的资源,因为update表的时候,oracle需要生成 redo log和undo log;

此时最好的解决办法是insert数据时, 将表设置为nologging,速度是比较快的。

这个时候oracle只会生成最低限度的必须的redo log,而没有一点undo信息。如果有可能将index也删除,重建。先看看实验结果:

archivelog

操作类型

Redo大小(byte)

insert

10896388

append insert

11143288

nologging insert

11088572

nologging+append

29404

noarchivelog

操作类型

Redo大小(byte)

insert

11105144

append insert

29404

nologging insert

10894408

nologging+append

4964

数据库版本:

SQL> select * from v$version;

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

PL/SQL Release 11.2.0.4.0 - Production

CORE    11.2.0.4.0      Production

TNS for Linux: Version 11.2.0.4.0 - Production

NLSRTL Version 11.2.0.4.0 - Production

首先确认数据库处于非归档模式

SQL> archive log list;

Database log mode           No Archive Mode

Automatic archival              Disabled

Archive destination            /u01/app/oracle/product/11.2.0/db_1/dbs/arch

Oldest online log sequence     692

Current log sequence           695

一、如果表采用默认的方式,也就是记录日志的方式,不管你是否使用insert into, oracle产生的日志都会很多

SQL> conn scott

Enter password:

Connected.

SQL>  create table tj as select * from dba_objects where 1=2;

SQL>  select count(*) from tj;

COUNT(*)

----------

0

SQL> select table_name,logging from user_tables where table_name='TJ';

TABLE_NAME                     LOG

------------------------------ ---

TJ                             YES

通过autotrace统计redo生成

SQL> set autotrace trace stat

1.直接insert插入

SQL> insert into tj select * from dba_objects;

95167 rows created.

Statistics

----------------------------------------------------------

188  recursive calls

12890  db block gets

3592  consistent gets

10  physical reads

11105144  redo size

837  bytes sent via SQL*Net to client

793  bytes received via SQL*Net from client

3  SQL*Net roundtrips to/from client

12  sorts (memory)

0  sorts (disk)

95167  rows processed

SQL>  rollback;

Rollback complete.

2.采用append 的方式

SQL> insert /*+ append */ into  tj select * from dba_objects;

95167 rows created.

Statistics

----------------------------------------------------------

37  recursive calls

1715  db block gets

1240  consistent gets

0  physical reads

29404  redo size

823  bytes sent via SQL*Net to client

808  bytes received via SQL*Net from client

3  SQL*Net roundtrips to/from client

1  sorts (memory)

0  sorts (disk)

95167  rows processed

SQL> rollback;

Rollback complete.

通过以上1和2两种不同方式的比较,我们发现产生的日志量减少很多11105144  redo size

29404  redo size

二、修改表为不记录日志,这个时候insert into就会体现出他的优势

1. 直接insert插入

SQL> alter table tj nologging;

Table altered.

SQL> insert into tj select * from dba_objects;

95167 rows created.

Statistics

----------------------------------------------------------

40  recursive calls

10145  db block gets

3957  consistent gets

0  physical reads

10894408  redo size

840  bytes sent via SQL*Net to client

793  bytes received via SQL*Net from client

3  SQL*Net roundtrips to/from client

7  sorts (memory)

0  sorts (disk)

95167  rows processed

SQL>  rollback;

Rollback complete.

2.采用append 的方式

SQL> insert /*+ append */ into  tj select * from dba_objects;

95167 rows created.

Statistics

----------------------------------------------------------

0  recursive calls

1419  db block gets

1204  consistent gets

0  physical reads

4964  redo size

826  bytes sent via SQL*Net to client

808  bytes received via SQL*Net from client

3  SQL*Net roundtrips to/from client

1  sorts (memory)

0  sorts (disk)

95167  rows processed

通过以上1和2两种不同方式的比较,我们发现产生的日志量APPEND的方式明显会少,10894408  redo size

4964  redo size

根据上面的实验我们可以发现,为了通过减少REDO而提高语句的性能,我们要满足两个条件1.表NOLOGGING 2.在语句中使用APPEND提示。

当然我们这里只是在强调性能,作为一个DBA,在性能和安全之间一定要做一个平衡,当你选择了NOLOGGING的时候,由于表是不记录日志的,那如果数据库崩溃,这些数据是不能被恢复的。

noarchivelog:

insert:           11105144  redo size

append:              29404  redo size

nologging:        10894408  redo size

nologging+append:     4964  redo size

下面是一个小的例子,当我们把一个表设置成NOLOGGING模式的时候,通过合适的操作,可以让oracle产生很少的REDO。

首先确认数据库处于归档模式

SQL>archive log list

Database log mode           Archive Mode

Automatic archival             Enabled

Archive destination            /u01/app/oracle/product/11.2.0/db_1/dbs/arch

Oldest online log sequence     692

Next log sequence to archive   695

Current log sequence           695

一、如果表采用默认的方式,也就是记录日志的方式,不管你是否使用insert into, oracle产生的日志都会很多

SQL> conn scott

Enter password:

Connected.

SQL>  create table tj as select * from dba_objects where 1=2;

Table created.

SQL>  select count(*) from tj;

COUNT(*)

----------

0

SQL> select table_name,logging from user_tables where table_name='TJ';

TABLE_NAME                     LOG

------------------------------ ---

TJ                             YES

通过autotrace统计redo生成

SQL> set autotrace trace stat

1.直接insert方式插入

SQL> insert into tj select * from dba_objects;

95167 rows created.

Statistics

----------------------------------------------------------

402  recursive calls

10107  db block gets

4200  consistent gets

19  physical reads

10896388  redo size

835  bytes sent via SQL*Net to client

793  bytes received via SQL*Net from client

3  SQL*Net roundtrips to/from client

33  sorts (memory)

0  sorts (disk)

95167  rows processed

SQL>  rollback;

Rollback complete.

2.采用append 提示的方式

SQL> insert /*+ append */ into  tj select * from dba_objects;

95167 rows created.

Statistics

----------------------------------------------------------

15  recursive calls

1395  db block gets

1208  consistent gets

22  physical reads

11143288  redo size

823  bytes sent via SQL*Net to client

808  bytes received via SQL*Net from client

3  SQL*Net roundtrips to/from client

1  sorts (memory)

0  sorts (disk)

95167  rows processed

SQL> rollback;

Rollback complete.

通过以上1和2两种不同方式的比较,我们发现产生的日志量没有减少10896388  redo size

11143288  redo size

二、修改表为不记录日志,这个时候insert into就会体现出他的优势

1.不采用append 提示

SQL>alter table tj nologging;

Table altered.

SQL>  select table_name,logging from user_tables where table_name='TJ';

TABLE_NAME                     LOG

------------------------------ ---

TJ                             NO

SQL>insert into tj select * from dba_objects;

95167 rows created.

Statistics

----------------------------------------------------------

50  recursive calls

12847  db block gets

3423  consistent gets

3  physical reads

11088572  redo size

836  bytes sent via SQL*Net to client

793  bytes received via SQL*Net from client

3  SQL*Net roundtrips to/from client

2  sorts (memory)

0  sorts (disk)

95167  rows processed

SQL>  rollback;

Rollback complete.

2.采用append 的方式

SQL> insert /*+ append */ into  tj select * from dba_objects;

95167 rows created.

Statistics

----------------------------------------------------------

37  recursive calls

1714  db block gets

1240  consistent gets

0  physical reads

29404  redo size

824  bytes sent via SQL*Net to client

808  bytes received via SQL*Net from client

3  SQL*Net roundtrips to/from client

1  sorts (memory)

0  sorts (disk)

95167  rows processed

通过以上1和2两种不同方式的比较,我们发现产生的日志量APPEND的方式明显会少,11088572  redo size

29404  redo size

根据上面的实验我们可以发现,为了通过减少REDO而提高语句的性能,我们要满足两个条件1.表NOLOGGING 2.在语句中使用APPEND提示。

当然我们这里只是在强调性能,作为一个DBA,在性能和安全之间一定要做一个平衡,当你选择了NOLOGGING的时候,由于表是不记录日志的,那如果数据库崩溃,这些数据是不能被恢复的。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐