本文主要是介绍聊聊Append、nologging和Redo Log,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
刚刚接触Oracle的时候,Append+Nologging可以减少Redo Size的说法在网络上讨论的很广。各种流言频出,混淆了很多人的概念体系。之后,一些牛人自此着手,澄清了很多的概念和观点。
老实说:我们不是Oracle的设计者,也没有机会研读源代码。实验看看是一种最简单、也是最直接的验证手段。本篇就一起将archive log/noarchive log、append、nologging和Redo Log几个关系重做实验,权当是自我实践,仿前人之路。
1、聊聊问题起源
很多偶然发生的历史事件,造就了今天的我们。
起源自一个问题:我们如何能够在进行DML(主要是insert)过程中快一点?影响DML的因素很多,其中一条就是Redo Log的生成。Redo Log的生成会引起之后的log buffer使用、LGWR激发、IO写入、Redo Log Switch和之后的Archive动作。那个时代的很多同行对于Redo Log有很多想法,于是问题变成了:我们怎么样可以减少一个insert的Redo Log生成。
那个时代的朋友提出了append和nologging策略。将数据表的logging属性关闭,在插入的时候使用append hint,可以减少Redo Log生成。一度网络上流言认为还可以不生成Redo Log。
“实践出真知”,下面我们通过一系列的实验对比,来重温一下这个思路过程。
2、实验环境介绍
我们选择Oracle 11R2进行实验。注意:不同的数据库版本在这个问题上的行为可能存在差异。笔者此处是就事论事,仅讨论11gR2。
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
创建两张数据表T_LOGGING和T_NOLOGGING,结构相同,差异就在数据表的logging属性上。
SQL> create table t_logging as select * from dba_objects where 1=0;
Table created
SQL> create table t_nologging nologging as select * from dba_objects where 1=0;
Table created
SQL> select table_name, logging from dba_tables where owner='SCOTT' and table_name in ('T_LOGGING','T_NOLOGGING');
TABLE_NAME LOGGING
------------------------------ -------
T_NOLOGGING NO
T_LOGGING YES
我们怎么样统计汇总Redo Log生成呢?借助v$mystat视图,可以发现其中关于redo log size的统计信息。执行insert前后分别执行这个语句,通过差值可以估算出Redo Log Size情况。
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
----------------------------- ----------
redo size 42456
redo size for lost write detection 0
redo size for direct writes 0
下面,分别从noarchived模式和archived模式看实际的效果差异。
3、NoArchived情况
我们先看看非归档模式下的实验情况。数据库此时运行在非归档模式下。
SQL> archive log list;
Database log mode No Archive Mode
Automatic archival Disabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 477
Current log sequence 479
开始进行测试,测试是没有关闭logging属性的数据表T_LOGGING。
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
------------------------------------------------------- ----------
redo size 85664
redo size for lost write detection 0
redo size for direct writes 0
SQL> insert into T_LOGGING select * from dba_objects;
72767 rows inserted
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
--------------------------------------------------- ----------
redo size 8593336
redo size for lost write detection 0
redo size for direct writes 0
SQL> rollback;
Rollback complete
两次度量的差额为:8593336-85664=8507672
下面进行NOLOGGING数据表测试。
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
--------------------------------------------- ----------
redo size 9150492
redo size for lost write detection 0
redo size for direct writes 0
SQL> insert into T_NOLOGGING select * from dba_objects;
72767 rows inserted
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
------------------------------------------------------ ----------
redo size 17666980
redo size for lost write detection 0
redo size for direct writes 0
SQL> rollback;
Rollback complete
两次度量的差额为:17666980-9150492=8516488。
我们发现:作为nologging的T_NOLOGGING,其在非归档模式下,生成日志量比LOGGING模式的数据表还大一些。没有明显的优势。
下面我们将APPEND加入进来,看看NOLOGGING能否有一些变化。
--清理环境
SQL> truncate table t_logging;
Table truncated
SQL> truncate table t_nologging;
Table truncated
--加入append
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
--------------------------------------------------- ----------
redo size 18304400
redo size for lost write detection 0
redo size for direct writes 0
SQL> insert /*+append */into T_NOLOGGING select * from dba_objects;
72767 rows inserted
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
----------------------------------------------------- ----------
redo size 18361040
redo size for lost write detection 0
redo size for direct writes 2236
SQL> rollback;
Rollback complete
两次度量的差额:18361040-18304400=56640,此外还有2236的direct writes类型的Redo Size。这个度量值要大大小于我们之前的测算。
说明:在非归档模式下,使用append和nologging可以减少Redo Size的生成。
下面看看归档模式的情况。
4、Archived Log情况
切换到Archived Log模式。
SQL> archive log list;
Database log mode Archive Mode
Automatic archival Enabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 478
Next log sequence to archive 480
Current log sequence 480
先进行logging模式的测试。
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
----------------------------------------------------- ----------
redo size 804
redo size for lost write detection 0
redo size for direct writes 0
SQL> insert into T_LOGGING select * from dba_objects;
72767 rows inserted
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
------------------------------------------------ ----------
redo size 8511740
redo size for lost write detection 0
redo size for direct writes 0
SQL> rollback;
Rollback complete
两次度量差额为:8511740-804=8510936。比之前非归档情况下实验redo log生成量略大一些。
下面是nologging数据表情况。
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
------------------------------------------------ ----------
redo size 9068376
redo size for lost write detection 0
redo size for direct writes 0
SQL> insert into T_NOLOGGING select * from dba_objects;
72767 rows inserted
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
------------------------------------------ ----------
redo size 17579204
redo size for lost write detection 0
redo size for direct writes 0
SQL> rollback;
Rollback complete
两次度量差额:17579204-9068376=8510828。和Logging比,生成的Redo Log Size是略大一点点。
加入append之后呢?
SQL> truncate table t_logging;
Table truncated
SQL> truncate table t_nologging;
Table truncated
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
---------------------------------------------------- ----------
redo size 18217420
redo size for lost write detection 0
redo size for direct writes 0
SQL> insert /*+append*/into T_NOLOGGING select * from dba_objects;
72767 rows inserted
SQL> select sn.NAME, ms.VALUE
2 from v$statname sn, v$mystat ms
3 where sn.STATISTIC#=ms.STATISTIC#
4 and sn.NAME like '%redo size%';
NAME VALUE
---------------------------------------------------- ----------
redo size 18274060
redo size for lost write detection 0
redo size for direct writes 2236
SQL> rollback;
Rollback complete
两次度量的差额为:56640,外加2236的direct writes的Redo Log生成量。这个和我们在非归档模式下append+nologging的取值是一样的!
5、结论
下面通过一张表格将实验数据进行汇总。
归档模式 | Insert语句 | Redo Size |
非归档 | Logging | 8507672 |
NoLogging | 8516488 | |
Append+Nologging | 56640+2236 | |
归档 | Logging | 8510936 |
NoLogging | 8510828 | |
Append+Nologging | 56640+2236 |
从实验结果上看,的确使用append+nologging可以减少Redo Log的生成。但是,这样就可以了吗?
回到问题的出发点,在Insert故障中,究竟有多少Redo Log Size减少以提升的空间。老实说,从实践领域看,insert出现性能问题的概率是比较小的。如果使用堆表Heap Table,而且数据表没有过多的索引对象,我们insert大部分的消耗是在空间拓展上。
Redo Log在insert过程中最大问题点在于Redo Log Group Member过小,引起频繁的切换动作。这种现象完全可以通过增大Redo Log Size和Group数量来缓解。
从另一个角度看,我们少生成了Redo Log,失去了什么?Redo Log是Oracle进行数据恢复动作的重要构成。少量Redo Log Size的生成,给我们带来的是日后恢复过程中难以想象的恶果。这个将在笔者下篇文章进行介绍。
如果是生产环境,强烈建议不要使用nologging+append策略进行插入动作。
这篇关于聊聊Append、nologging和Redo Log的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!