Refazer limite para atualização completa da visualização materializada ou equivalente manual

10

Um log de visualização materializada (MV) pode ser usado para permitir que uma MV faça uma atualização rápida que modifica apenas os dados que foram alterados. No entanto, várias condições impedem que o MV use o log e, portanto, requerem uma atualização completa. A Oracle implementou uma atualização completa atômica como uma exclusão e inserção de cada registro. Isso é feito mesmo que não haja alterações nos dados.

Existe uma maneira de tornar essa replicação inteligente em relação à refazer geração ? Um MERGE seguido por um DELETE requer consultar a fonte duas vezes. Valeria a pena coletar os dados em massa para fazer uma BULK MERGE e DELETE? Existe uma maneira melhor?

Atualizar:

Eu explorei usando uma tabela temporária global como uma área de preparação. Embora eles usem menos da metade do refazer, eles ainda usam muito.

Leigh Riffel
fonte
Você pode postar o código gtt? gtt não gera refazer diretamente, mas gera desfazer - e desfazer gera refazer. insertAs operações geram muito menos desfazer deleteou updateoperações (quase nenhuma de fato). Tendo vários gtts para evitar quaisquer ops caros pode ser uma abordagem bem
Jack diz tentar topanswers.xyz
@Jack Douglas psoug.org/reference/gtt.html possui uma demonstração da geração de refazer GTT mostrando uma redução de 60% no refazer entre uma tabela física e um GTT para inserts. Isso se aproxima dos resultados que estou vendo e é melhor, mas não tão bom quanto eu gostaria.
Leigh Riffel 14/06
Esses testes (linha por linha e nenhuma appenddica) não são condições ideais para reduzir o refazer - executei alguns testes para mostrar o que quero dizer. Postado como resposta, porque eles não cabem em um comentário
Jack diz que tenta topanswers.xyz

Respostas:

5

Pretende-se apenas demonstrar o uso refazer de várias insertoperações, em vez de responder a toda a pergunta. Os resultados na minha instância de 10g não são 100% determinísticos, mas o quadro geral permaneceu o mesmo toda vez que eu corria.

Para as tabelas de heap, não sei por que o insert /*+ append */gerado refaz mais.

testbed:

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);

teste:

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';

resultado:

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                   
Jack diz que tenta topanswers.xyz
fonte
Você está correto, é claro. Eu deveria ter percebido isso nos testes deles. Vou dar uma chance.
Leigh Riffel
6

Boa pergunta. Eu "resolvi" esse problema para a minha situação há algum tempo, fazendo os MVs e quaisquer índices neles NOLOGGING. Não havia sentido em minha situação - de qualquer maneira, eu estava atualizando completamente a exibição, por que precisaria refazer?

DCookie
fonte
11
Você também pode precisar de ATOMIC_REFRESH = false (em 10g e acima). Não sabe ao certo quais são as implicações para qualquer banco de dados em espera ou recuperação com logs de arquivamento?
Jack diz que tente topanswers.xyz 12/06
Eu executo uma espera lógica e física no banco de dados com o qual fiz isso. Não há problemas lá. Eu tive um problema ao fazer cópias de banco de dados - tenho que examinar minhas anotações, mas às vezes havia um erro sobre a recuperação em um espaço de tabela com tabelas de registro. Li as recomendações para criar um espaço de tabela reservado para tabelas / índices que não são de registro em log para evitar esses problemas. Eu descobri como resolvê-lo embora.
DCookie
@ Jack, acredito que tive que usar a atualização não atômica.
DCookie
Hmmm, se eu usar uma visão materializada padrão, ela precisará fazer uma atualização atômica, para que isso não funcione para mim. Outra pessoa pode achar útil, por isso ainda é uma boa resposta.
Leigh Riffel
Por que ele precisa de uma atualização atômica? Pelo que entendi, definir isso como false afeta apenas uma atualização COMPLETA. Veja esta postagem da asktom: asktom.oracle.com/pls/apex/…
DCookie