限制重做以实例化视图完全刷新或手动等效


10

物化视图(MV)日志可用于允许MV执行快速刷新,该刷新仅修改已更改的数据。但是,各种情况都会阻止MV使用日志,因此需要完全刷新。Oracle实现了原子的完全刷新,作为每个记录的删除和插入。即使最终数据没有变化,它也会这样做。

有没有办法使这种复制在重做生成方面变得智能化?合并后跟删除要求将源查询两次。批量收集数据进行批量合并和删除是否值得?有没有更好的办法?

更新:

我探索了使用全局临时表作为暂存区。尽管他们使用的重做少于一半,但仍然使用很多。


您可以发布gtt代码吗?gtt不会直接生成重做,但它们确实会生成撤消-撤消会生成重做。insert操作产生的撤消操作比deleteupdate操作少(实际上几乎没有)。拥有多个gtts以避免任何昂贵的操作可能是个好方法
杰克说,请尝试topanswers.xyz 2011年

@Jack Douglas psoug.org/reference/gtt.html有一个GTT重做生成演示,显示了物理表和inserts 的GTT之间的重做减少了60%。这与我所看到的结果非常匹配,并且更好,但不如我想要的好。
Leigh Riffel

这些测试(逐行且无append提示)不是减少重做的理想条件-我已经运行了一些测试以表明我的意思。作为答案发布,因为它们不适合评论
杰克说尝试topanswers.xyz 2011年

Answers:


5

这仅是为了演示各种insert操作的重做用法,而不是回答整个问题。我的10g实例的结果不是100%确定性的,但是每次运行时,总体情况都是一样的。

对于堆表,我不知道为什么insert /*+ append */生成更多的重做。

测试平台:

create table heap_noappend(id integer, dummy char(500));
create table heap_append(id integer, dummy char(500));
create global temporary table gtt_noappend(id integer, dummy char(500));
create global temporary table gtt_append(id integer, dummy char(500));
create global temporary table gtt_results(stage integer, val integer);

测试:

insert into gtt_results(stage, val)
select 0, value from v$statname join v$sesstat using(statistic#)
where sid=sys_context('userenv','sid') and name='redo size';

insert into heap_noappend(id, dummy)
select level, 'A' from dual connect by level<1000;

insert into gtt_results(stage, val)
select 1, value from v$statname join v$sesstat using(statistic#)
where sid=sys_context('userenv','sid') and name='redo size';

insert /*+ append */ into heap_append(id, dummy)
select level, 'A' from dual connect by level<1000;

insert into gtt_results(stage, val)
select 2, value from v$statname join v$sesstat using(statistic#)
where sid=sys_context('userenv','sid') and name='redo size';

insert into gtt_noappend(id, dummy)
select level, 'A' from dual connect by level<1000;

insert into gtt_results(stage, val)
select 3, value from v$statname join v$sesstat using(statistic#)
where sid=sys_context('userenv','sid') and name='redo size';

insert /*+ append */ into gtt_append(id, dummy)
select level, 'A' from dual connect by level<1000;

insert into gtt_results(stage, val)
select 4, value from v$statname join v$sesstat using(statistic#)
where sid=sys_context('userenv','sid') and name='redo size';

结果:

select * 
from( select decode(stage,1,'heap noappend',
                          2,'heap append',
                          3,'gtt noappend',
                          4,'gtt append') as operation, 
             val-lag(val) over(order by stage) as redo 
      from gtt_results)
where redo is not null;

OPERATION     REDO                   
------------- ---------------------- 
heap noappend 606932                 
heap append   690768                 
gtt noappend  41488                  
gtt append    256                   

你当然是对的。我应该在他们的测试中发现这一点。我会尝试的。
Leigh Riffel

6

好问题。通过将MV及其上的任何索引设为NOLOGGING,我为自己的情况“解决”了一段时间。我的情况无济于事-无论如何我都在刷新视图,为什么我需要重做?


1
您可能还需要ATOMIC_REFRESH = false(10g及以上)。不确定任何备用数据库或使用归档日志进行恢复的含义是什么?
杰克说请尝试topanswers.xyz 2011年

我在执行此操作的数据库上运行逻辑和物理备用数据库。那里没有问题。我确实遇到了制作数据库副本的问题-必须看一下我的笔记,但是有时会出现关于在不记录表的表空间上执行恢复的错误。我已阅读有关为未记录的表/索引创建保留表空间的建议,以避免此类问题。我确实想出了解决方法。
DCookie

@杰克,我相信我必须使用非原子刷新。
DCookie

嗯,如果我使用标准的实例化视图,则需要进行原子刷新,因此这对我不起作用。其他人可能会发现它有用,因此仍然是一个不错的答案。
Leigh Riffel

为什么需要原子刷新?据我了解,将其设置为false仅会影响完全刷新。请参阅以下Asktom
DCookie
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.