关于table logging 和 archive log 两个参数对归档日志起到的作用

本文详细对比了Oracle数据库在非归档模式和归档模式下,通过不同批量插入方式对redo日志的影响,并提供了优化建议。主要分为三部分:非归档模式下通过insert/*+append*/into方式减少redo产生;归档模式下设置表的logging属性为false以减少redo;最后对比了在归档模式下几种批量插入操作的效率。优化建议包括设置表为nologging状态,以降低redo日志的生成,提高批量数据加载性能。

一 非归档模式下

D:>sqlplus "/ as sysdba"

数据库版本为9.2.0.1.0

SQL*Plus: Release 9.2.0.1.0 - Production on 星期一 8月 14 10:20:39 2006

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.



连接到:
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production

当前session产生的redo
SQL> create or replace view redo_size
2 as
3 select value
4 from v$mystat, v$statname
5 where v$mystat.statistic# = v$statname.statistic#
6 and v$statname.name = 'redo size';

视图已建立。

授权给相应数据库schema
SQL> grant select on redo_size to liyong;

授权成功。

SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。

SQL> startup mount;
ORACLE 例程已经启动。

Total System Global Area 122755896 bytes
Fixed Size 453432 bytes
Variable Size 88080384 bytes
Database Buffers 33554432 bytes
Redo Buffers 667648 bytes
数据库装载完毕。

非归档模式
SQL> alter database noarchivelog;

数据库已更改。

SQL> alter database open;

数据库已更改。

SQL> create table redo_test as
2 select * from all_objects where 1=2;

表已创建。

SQL> select * from sys.redo_size;

VALUE
----------
59488

SQL> insert into redo_test
2 select * from all_objects;

已创建28260行。

SQL> select * from sys.redo_size;

VALUE
----------
3446080

SQL> insert /*+ append */ into redo_test
2 select * from all_objects;

已创建28260行。

SQL> commit;

提交完成。

SQL> select * from sys.redo_size;

VALUE
----------
3458156

可以看到insert /*+ append */ into方式redo产生很少.
SQL> select 3446080-59488,3458156-3446080 from dual;

3446080-59488 3458156-3446080
------------- ---------------
3386592 12076

将表redo_test置为nologging状态.
SQL> alter table redo_test nologging;

表已更改。

SQL> select * from sys.redo_size;

VALUE
----------
3460052

SQL> insert into redo_test
2 select * from all_objects;

已创建28260行。

SQL> commit;

提交完成。

SQL> select * from sys.redo_size;

VALUE
----------
6805876

SQL> insert /*+ append */ into redo_test
2 select * from all_objects;

已创建28260行。

SQL> commit;

提交完成。

SQL> select * from sys.redo_size;

VALUE
----------
6818144

非归档模式下表的nologging状态对于redo影响不大
SQL> select 6805876-3460052,6818144-6805876 from dual;

6805876-3460052 6818144-6805876
--------------- ---------------
3345824 12268


结论: 在非归档模式下通过insert /*+ append */ into方式批量加载数据可以大大减少redo产生.

二 归档模式下


SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SQL> startup mount;
ORACLE 例程已经启动。

Total System Global Area 122755896 bytes
Fixed Size 453432 bytes
Variable Size 88080384 bytes
Database Buffers 33554432 bytes
Redo Buffers 667648 bytes
数据库装载完毕。
SQL> alter database archivelog;

数据库已更改。

SQL> alter database open;

数据库已更改。

SQL> conn liyong
请输入口令:
已连接。


将表redo_test重新置为logging
SQL> alter table redo_test logging;

表已更改。

SQL> select * from sys.redo_size;

VALUE
----------
5172

SQL> insert into redo_test
2 select * from all_objects;

已创建28260行。

SQL> commit;

提交完成。

SQL> select * from sys.redo_size;

VALUE
----------
3351344

SQL> insert /*+ append */ into redo_test
2 select * from all_objects;

已创建28260行。

SQL> commit;

提交完成。

SQL> select * from sys.redo_size;

VALUE
----------
6659932

可以看到在归档模式下,且表的logging属性为true,insert /*+ append */ into这种方式也会纪录大量redo
SQL> select 3351344-5172,6659932-3351344 from dual;

3351344-5172 6659932-3351344
------------ ---------------
3346172 3308588


将表置为nologging

SQL> alter table redo_test nologging;

表已更改。

SQL> select * from sys.redo_size;

VALUE
----------
6661820

SQL> insert into redo_test
2 select * from all_objects;

已创建28260行。

SQL> commit;

提交完成。

SQL> select * from sys.redo_size;

VALUE
----------
10008060

SQL> insert /*+ append */ into redo_test
2 select * from all_objects;

已创建28260行。

SQL> commit;

提交完成。

SQL> select * from sys.redo_size;

VALUE
----------
10022852

可以发现在归档模式,要设置表的logging属性为false,才能通过insert /*+ append */ into大大减少redo产生.
SQL> select 10008060-6661820,10022852-10008060 from dual;

10008060-6661820 10022852-10008060
---------------- -----------------
3346240 14792

结论: 在归档模式下,要设置表的logging属性为false,
才能通过insert /*+ append */ into大大减少redo.

三 下面我们再看一下在归档模式下,几种批量insert操作的效率对比.

redo_test表有45W条记录

SQL> select count(*) from redo_test;

COUNT(*)
----------
452160


1 最常见的批量数据加载 25秒

SQL> create table insert_normal as
2 select * from redo_test where 0=2;

表已创建。

SQL> set timing on

SQL> insert into insert_normal
2 select * from redo_test;

已创建452160行。

提交完成。
已用时间: 00: 00: 25.00


2 使用insert /*+ append */ into方式(这个的原理可以参见<<批量DML操作优化建议.txt>>),但纪录redo. 17.07秒
SQL> create table insert_hwt
2 as
3 select * from redo_test where 0=2;

表已创建。
SQL> insert /*+ append */ into insert_hwt
2 select * from redo_test;

已创建452160行。

提交完成。
已用时间: 00: 00: 17.07


3 使用insert /*+ append */ into方式,且通过设置表nologging不纪录redo.

SQL> create table insert_hwt_with_nologging nologging
2 as
3 select * from redo_test where 2=0;

表已创建。

/*
或者通过
alter table table_name nologging设置
*/

SQL> insert /*+ append */ into insert_hwt_with_nologging 11.03秒
2 select * from redo_test;

已创建452160行。

提交完成。
已用时间: 00: 00: 11.03

总结:

我们看到对于批量操作,如果设置表nologging,可以大大提高性能.原因就是Oracle没有纪录DML所产生的redo.
当然,这样会影响到备份。nologging加载数据后要做数据库全备.

jolly10 发表于:2008.03.18 13:19 ::分类: ( 转载学习内容 ) ::阅读:(1097次) :: 评论 (3) :: 引用 (0)
re: Oracle的Nologging何时生效 与 批量insert加载数据速度(zt) [回复]

下面我又试了试insert into XXX values (XXX)能不能少产生redo,做了试验发现,不行的,下面的过程.
SQL> select * from v$version where rownum archive log list;
Database log mode No Archive Mode
Automatic archival Disabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 17
Current log sequence 19

SQL> create or replace view redo_size
2 as
3 select value
4 from v$mystat, v$statname
5 where v$mystat.statistic# = v$statname.statistic#
6 and v$statname.name = 'redo size';

View created.

SQL> grant select on redo_size to ljg;

SQL> conn ljg/ljg
Connected.

SQL> create table redo_test as
2 select * from all_objects where 1=2;

SQL> CREATE OR REPLACE PROCEDURE p_loging
2 as
3 CURSOR c_a IS
4 SELECT * FROM all_objects;
5
6 BEGIN
7 FOR x IN c_a LOOP
8 INSERT INTO REDO_TEST
9 VALUES(x.OWNER, x.OBJECT_NAME, x.SUBOBJECT_NAME, x.OBJECT_ID, x.DATA_OBJE CT_ID,
10 x.OBJECT_TYPE, x.CREATED, x.LAST_DDL_TIME, x.TIMESTAMP, x.STATUS, x.TEMPORARY, x.GENERATED, x.SECONDARY);
11 END LOOP;
12 COMMIT;
13
14 END;
15 /

Procedure created.

SQL> CREATE OR REPLACE PROCEDURE p_nologing
2 as
3 CURSOR c_a IS
4 SELECT * FROM all_objects;
5
6 BEGIN
7 FOR x IN c_a LOOP
8 INSERT /*+ APPEND */ INTO REDO_TEST
9 VALUES(x.OWNER, x.OBJECT_NAME, x.SUBOBJECT_NAME, x.OBJECT_ID, x.DATA_OBJECT_ID,
10 x.OBJECT_TYPE, x.CREATED, x.LAST_DDL_TIME, x.TIMESTAMP, x.STATUS, x.TEMPORARY, x.GENERATED, x.SECONDARY);
11 END LOOP;
12 COMMIT;
13
14 END;
15 /

Procedure created.

SQL> select * from sys.redo_size;

VALUE
----------
85940

SQL> exec p_loging;

PL/SQL procedure successfully completed.

SQL> select * from sys.redo_size;

VALUE
----------
15273968

SQL> exec p_nologing;

PL/SQL procedure successfully completed.

SQL> select * from sys.redo_size;

VALUE
----------
30411272

SQL> select 15273968- 85940 logging,30411272-15273968 nologging from dual;

LOGGING NOLOGGING
---------- ----------
15188028 15137304

可以看到nologging和logging产生的redo差不多.

jolly10 评论于:2008.06.05 11:07
re: Oracle的Nologging何时生效 与 批量insert加载数据速度(zt) [回复]

下面我又试了试insert into XXX values (XXX)能不能少产生redo,做了试验发现,不行的,下面的过程.
SQL> select * from v$version where rownum archive log list;
Database log mode No Archive Mode
Automatic archival Disabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 17
Current log sequence 19

SQL> create or replace view redo_size
2 as
3 select value
4 from v$mystat, v$statname
5 where v$mystat.statistic# = v$statname.statistic#
6 and v$statname.name = 'redo size';

View created.

SQL> grant select on redo_size to ljg;

SQL> conn ljg/ljg
Connected.

SQL> create table redo_test as
2 select * from all_objects where 1=2;

SQL> CREATE OR REPLACE PROCEDURE p_loging
2 as
3 CURSOR c_a IS
4 SELECT * FROM all_objects;
5
6 BEGIN
7 FOR x IN c_a LOOP
8 INSERT INTO REDO_TEST
9 VALUES(x.OWNER, x.OBJECT_NAME, x.SUBOBJECT_NAME, x.OBJECT_ID, x.DATA_OBJE CT_ID,
10 x.OBJECT_TYPE, x.CREATED, x.LAST_DDL_TIME, x.TIMESTAMP, x.STATUS, x.TEMPORARY, x.GENERATED, x.SECONDARY);
11 END LOOP;
12 COMMIT;
13
14 END;
15 /

Procedure created.

SQL> CREATE OR REPLACE PROCEDURE p_nologing
2 as
3 CURSOR c_a IS
4 SELECT * FROM all_objects;
5
6 BEGIN
7 FOR x IN c_a LOOP
8 INSERT /*+ APPEND */ INTO REDO_TEST
9 VALUES(x.OWNER, x.OBJECT_NAME, x.SUBOBJECT_NAME, x.OBJECT_ID, x.DATA_OBJECT_ID,
10 x.OBJECT_TYPE, x.CREATED, x.LAST_DDL_TIME, x.TIMESTAMP, x.STATUS, x.TEMPORARY, x.GENERATED, x.SECONDARY);
11 END LOOP;
12 COMMIT;
13
14 END;
15 /

Procedure created.

SQL> select * from sys.redo_size;

VALUE
----------
85940

SQL> exec p_loging;

PL/SQL procedure successfully completed.

SQL> select * from sys.redo_size;

VALUE
----------
15273968

SQL> exec p_nologing;

PL/SQL procedure successfully completed.

SQL> select * from sys.redo_size;

VALUE
----------
30411272

SQL> select 15273968- 85940 logging,30411272-15273968 nologging from dual;

LOGGING NOLOGGING
---------- ----------
15188028 15137304

可以看到nologging和logging产生的redo差不多.

jolly10 评论于:2008.06.05 11:07
re: Oracle的Nologging何时生效 与 批量insert加载数据速度(zt) [回复]

在ITPUB中问到可以用BULK COLLECT 来减少insert into values的redo.
CREATE OR REPLACE PROCEDURE p_BulkAdd
AS
TYPE Tredo_test IS TABLE OF REDO_TEST%ROWTYPE;
V_REDO_TEST Tredo_test;
BEGIN
SELECT * BULK COLLECT INTO V_REDO_TEST FROM ALL_OBJECTS;
FORALL X IN V_REDO_TEST.FIRST..V_REDO_TEST.LAST
INSERT INTO REDO_TEST VALUES V_REDO_TEST(X);
END;
/

SQL> select * from sys.redo_size;

VALUE
----------
30411272

SQL> exec p_bulkadd;

PL/SQL procedure successfully completed.

SQL> select * from sys.redo_size;

VALUE
----------
35050796

SQL> select 35050796-30411272 from dual;

35050796-30411272
-----------------
4639524

这个做的确是少了很多redo.是一个方法.

<think>好的,我现在需要处理用户的问题:Oracle数据库每天产生500G归档日志,怎么优化?首先,我得理解归档日志为什么会这么大,以及可能的原因解决方法。 首先,用户提到每天500G的归档日志,这在生产环境中确实是一个比较高的量。归档日志的大小主要数据库的事务量有关,尤其是频繁的DML操作(比如插入、更新、删除)。另外,可能的原因包括:未优化的批量操作、过高的日志生成参数设置、缺乏定期的维护,或者没有使用归档日志优化策略。 接下来,我需要分步骤考虑优化方向: 1. **分析归档日志来源**:需要确定是哪些操作导致大量日志生成。是否是正常的业务操作,还是有异常的批量作业?可以通过AWR报告或ASH报告查看高负载的SQL语句,或者检查V$ARCHIVED_LOG视图了解日志切换频率。 2. **检查数据库参数设置**:比如是否启用了强制日志(FORCE_LOGGING),这会记录所有操作到日志。另外,归档日志格式大小也可能影响,比如日志文件的大小设置是否合理。如果每个日志文件过小,频繁切换会导致更多文件产生,但总容量可能不会减少,但调整日志文件大小可能有助于管理。 3. **优化高DML操作**:例如批量数据处理是否可以使用DIRECT PATH插入(比如/*+ APPEND */提示),因为这种方式生成的redo日志较少。另外,NOLOGGING操作(在允许的情况下)可以减少日志量,但要注意数据恢复的风险。 4. **分区表维护**:如果对大表进行分区维护操作(如TRUNCATE PARTITION)可能产生大量日志,可以考虑分阶段处理或使用更高效的方式。 5. **评估归档日志保留策略**:检查RMAN的备份策略,是否保留过多的归档日志。可以通过调整RMAN的保留策略,删除过期的归档日志,或者启用归档日志的删除策略(比如CONFIGURE ARCHIVELOG DELETION POLICY TO ...)。 6. **使用Oracle Data Guard或ADG**:如果有备用库,可以考虑启用异步传输模式,减少主库的压力,或者调整归档日志传输的频率。 7. **压缩归档日志**:Oracle 11g及以上支持归档日志的压缩,可以在RMAN中启用压缩备份,或者在生成归档时启用压缩(需要确认版本支持情况)。 8. **评估业务需求**:是否真的需要所有操作都记录归档?例如,临时表空间或某些中间表是否可以使用NOLOGGING模式。 9. **定期维护监控**:定期分析归档日志增长趋势,及时调整策略。使用自动化脚本清理过期归档,但要确保备份已经完成。 可能遇到的问题包括:调整参数导致性能影响,NOLOGGING操作带来的数据恢复风险,压缩对CPU资源的消耗等,需要权衡利弊。 比如,如果发现某个夜间批量任务生成了大量日志,可以优化该任务的SQL,使用DIRECT PATH方式。或者检查是否有不必要的全表更新操作,改为更精确的更新条件。 另外,归档日志的存储位置是否有足够空间,是否可以考虑归档到不同的磁盘或使用ASM管理,虽然这不直接减少日志量,但有助于管理。 总结起来,步骤可能是:分析源头,调整参数,优化SQL操作,合理设置保留策略,使用压缩技术,定期维护。同时需要综合数据库的整体性能恢复要求来权衡优化措施。</think>针对Oracle数据库每天产生500G归档日志的优化问题,可按照以下步骤逐步处理: --- ### **1. 分析归档日志来源** - **查看高事务操作** 通过AWR/ASH报告或查询`V$SQLAREA`,定位高频DML语句(如批量INSERT/UPDATE/DELETE)。 示例查询高频SQL: ```sql SELECT sql_id, executions, disk_reads, buffer_gets, sql_text FROM v$sqlarea ORDER BY disk_reads DESC; ``` - **监控日志切换频率** 检查`V$ARCHIVED_LOG`统计每日日志切换次数: ```sql SELECT TO_CHAR(first_time, 'YYYY-MM-DD') AS day, COUNT(*) AS archive_log_count, SUM(blocks * block_size)/1024/1024/1024 AS total_size_GB FROM v$archived_log GROUP BY TO_CHAR(first_time, 'YYYY-MM-DD'); ``` --- ### **2. 调整数据库参数** - **禁用不必要的日志记录** 若未使用Data Guard,关闭`FORCE_LOGGING`: ```sql ALTER DATABASE NO FORCE LOGGING; ``` - **优化日志文件大小** 增大日志文件大小以减少切换频率(需重启生效): ```sql ALTER DATABASE ADD LOGFILE GROUP 4 ('/path/logfile4.log') SIZE 2G; ALTER DATABASE DROP LOGFILE GROUP 1; -- 删除旧的小日志组 ``` --- ### **3. 优化高DML操作** - **使用DIRECT PATH插入** 在批量插入时添加`/*+ APPEND */`提示,减少REDO生成: ```sql INSERT /*+ APPEND */ INTO table_name SELECT * FROM source_table; ``` - **合理使用NOLOGGING模式** 对中间表或可重建数据使用NOLOGGING: ```sql ALTER TABLE temp_table NOLOGGING; INSERT /*+ APPEND NOLOGGING */ INTO temp_table ...; ``` --- ### **4. 调整备份与保留策略** - **压缩归档日志** 在RMAN备份时启用压缩(需Oracle Advanced Compression许可): ```rman CONFIGURE COMPRESSION ALGORITHM 'BASIC' AS OF RELEASE 'DEFAULT' OPTIMIZE FOR LOAD TRUE; BACKUP AS COMPRESSED BACKUPSET ARCHIVELOG ALL DELETE INPUT; ``` - **自动清理过期归档** 设置RMAN保留策略,自动删除过期备份及归档: ```rman CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS; CROSSCHECK ARCHIVELOG ALL; DELETE EXPIRED ARCHIVELOG ALL; ``` --- ### **5. 启用归档日志实时压缩(11g+)** 在数据库层面启用REDO日志压缩(需Advanced Compression许可): ```sql ALTER SYSTEM SET ARCHIVE_LAG_TARGET=1800; -- 每30分钟切换一次日志 ALTER DATABASE ARCHIVELOG COMPRESS ENABLE; ``` --- ### **6. 分区表与维护优化** - **使用分区交换(Partition Exchange)** 对大表分区进行数据加载时,用`EXCHANGE PARTITION`减少日志: ```sql ALTER TABLE main_table EXCHANGE PARTITION partition_name WITH TABLE stage_table WITHOUT VALIDATION; ``` - **避免全表TRUNCATE** 优先使用`DROP PARTITION`代替`TRUNCATE`,减少UNDOREDO: ```sql ALTER TABLE partitioned_table DROP PARTITION old_partition; ``` --- ### **7. 定期维护与监控** - **自动化清理脚本** 添加定时任务清理已备份的归档日志(示例Shell脚本): ```bash rman target / <<EOF DELETE NOPROMPT ARCHIVELOG UNTIL TIME 'SYSDATE-3' BACKED UP 1 TIMES TO DEVICE TYPE DISK; EOF ``` - **监控归档增长趋势** 创建每日归档日志增长监控报表: ```sql SELECT TO_CHAR(first_time, 'YYYY-MM-DD') AS day, COUNT(*) AS logs_per_day, SUM(blocks * block_size)/1024/1024/1024 AS size_gb FROM v$archived_log GROUP BY TO_CHAR(first_time, 'YYYY-MM-DD') ORDER BY day DESC; ``` --- ### **总结优化效果** 通过上述步骤,预期优化效果如下: - **直接减少日志量**:通过NOLOGGING、DIRECT PATH等技术,减少30%~70%日志生成。 - **降低管理开销**:增大日志文件大小、压缩归档,降低存储压力备份时间。 - **可控保留周期**:通过RMAN策略避免无效归档堆积。 --- **注意事项**: - `NOLOGGING`操作后需立即备份相关数据,避免介质恢复失败。 - 调整日志文件大小时需确保在线日志组足够,防止日志切换等待。 - 压缩功能可能增加CPU负载,需评估硬件资源。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值