清理数据,需要删除1000万条记录,会产生多少归档日志,是否会撑爆归档空间?
首先看是用什么方法删除
drop table xxx; 可能只有几百k,无需担心
alter table xxx drop partition ppp; 也没多大
delete from xxx where riqi<'2022-03-02'; 这个就难说了,粗略的方法是:
1.切换一下归档日志
2.删除一部分,
例如1天的(假设数据每日差不多)或者100万条
3.再切换一次归档
4.看此期间的归档文件大小(如果产生多个,需要合计),再等比放大即可。
演示:
创建模拟数据
-
conn a/a
-
drop table big;
-
create table big as select b.*, sysdate riqi from dba_objects b where 1=2;
-
insert into big select b.*, to_date('2022-08-01','yyyy-mm-dd') riqi from dba_objects b;
-
insert into big select b.*, to_date('2022-08-02','yyyy-mm-dd') riqi from dba_objects b;
-
insert into big select b.*, to_date('2022-08-03','yyyy-mm-dd') riqi from dba_objects b;
-
insert into big select b.*, to_date('2022-08-04','yyyy-mm-dd') riqi from dba_objects b;
-
insert into big select b.*, to_date('2022-08-05','yyyy-mm-dd') riqi from dba_objects b;
-
insert into big select b.*, to_date('2022-08-06','yyyy-mm-dd') riqi from dba_objects b;
-
commit;
记录当前归档日志号,然后删除一部分数据,让oracle自己产生归档
-
conn /as sysdba
-
alter system switch logfile;
-
archive log list;
-
delete from a.big where riqi=to_date('2022-08-02','yyyy-mm-dd');
-
commit;
-
alter system switch logfile;
-
archive log list;
可见只生成了一个归档(其实就是执行alter system switch logfile 产生出来的),大小是13m,删除7万多条dba_objects 中的记录会产生这么多的归档,如果删除的数据有几百万,那么oracle写满一个redo后,会自动输出到归档日志里,可能看到很多个归档日志,加和即可,然后等比放大就是归档空间的总需求量。
开发人员看到此就可以退出了。
精确计算方法:
-
set serverout on
-
declare
-
l_redo1 number;
-
l_redo2 number;
-
begin
-
select ms.value
-
into l_redo1
-
from v$statname sn, v$mystat ms
-
where sn.statistic# = ms.statistic#
-
and lower(sn.name) = 'redo size';
-
-
-- your dml/ddl here
-
execute immediate 'delete from a.big where riqi=to_date(''2022-08-06'',''yyyy-mm-dd'')';
-
-
select ms.value
-
into l_redo2
-
from v$statname sn, v$mystat ms
-
where sn.statistic# = ms.statistic#
-
and lower(sn.name) = 'redo size';
-
-
dbms_output.put_line((l_redo2 - l_redo1) || ' bytes of redo generated');
-
end;
-
/
-
-
统计了几天的
-
-- 11774584 比实际的13m要小一些,应该是归档文件中还记录redo record 和文件头信息,需要占用一部分空间
-
-- 11711180
-
-- 11697676
看看归档日志的内容
-
alter system dump logfile 'filename'
-
scn min minimumscn
-
scn max maximumscn
-
time min minimumtime
-
time max maximumtime
-
layer layer
-
opcode opcode
-
dba min filenumber blocknumber
-
dba max filenumber blocknumber
-
rba min logfilesequencenumber blocknumber
-
rba max logfilesequencenumber blocknumber
-
objno objectnumber
-
xid undosegmentnumber undoslotnumber undosequencenumber;
-
-
-
例如:
-
alter system dump logfile '/arch/1_4873_1083135550.dbf';
会输出到一个trc文件中,比归档文件要大5倍左右
看看trc文件内容,深入了解archive log 文件包含的信息
头部信息都差不多
接着往下看,输出了文件头信息:数据库id,库名称,文件大小,thread号,sequence号,scn起止号等
继续往下看
会看到重做记录(redo record change#1 change #2)信息,本质上,archive log是redo log的副本,记录的是数据库变化,在oracle里被称为redo records,这些recordes由改变向量组成
record产生过程:
1.为undo记录创建改变向量
2.为数据库块创建改变向量
3.合并改变向量,并将构造好的redo记录写入重做日志缓冲区
4.将undo记录插入undo块中
5.真正改变数据库块
详细内容可参考《oracle core》书中第二章描述。
刚才看到生成的归档文件大小是13m,通过redo size统计信息看到的才11m,具体差在哪里呢?
需要了解redo record结构
还有改变向量的结构
可以看到redo block的大小是512或1024字节(select distinct block_size from v$archived_log;),与传统的块大小8k不一样。头部信息和空闲空间会导致生成的归档文件比redo size大出一些。
继续往下看,会看到执行了delete后,为了恢复,oracle会记录原始的信息col代表字段,第一个53 59 53 是十六进制,转换为字符就是sys,第二个转换一下:
就是dba_objects里的对象名称。
一模一样。
再有个问题:如何减少redo大小?
可考虑的措施如下:
1.消除冗余索引
2.减少更新的列数
3.消除多余的 select for update 语句
4.减少处理的行数
5.消除 commit 语句
6.增加批量大小
7.使用全局临时表
8.使用外部表
参考:
juliandyke.com
阅读(737) | 评论(0) | 转发(0) |