Limite ripetizione per l'aggiornamento materializzato della vista materializzata o equivalente manuale


10

Un registro di visualizzazione materializzata (MV) può essere utilizzato per consentire a un MV di eseguire un aggiornamento rapido che modifica solo i dati che sono stati modificati. Tuttavia, varie condizioni impediscono all'MV di utilizzare il registro e quindi richiedono un aggiornamento completo. Oracle ha implementato un aggiornamento atomico completo come eliminazione e inserimento di ogni record. Lo fa anche se alla fine non ci sono modifiche ai dati.

C'è un modo per rendere intelligente questa replica per quanto riguarda la generazione di ripetizioni ? Un MERGE seguito da un DELETE richiede di interrogare l'origine due volte. Ne varrebbe la pena raccogliere collettivamente i dati per eseguire un BULK MERGE e DELETE? C'è un modo migliore?

Aggiornare:

Ho esplorato usando una tabella temporanea globale come area di gestione temporanea. Anche se usano meno della metà della ripetizione, usano ancora molto.


Puoi pubblicare il codice gtt? gtt's non genera redo direttamente, ma genera annulla e annulla genera redo. insertops genera molto meno annulla di deleteo updateops (quasi nessuno in effetti). Avere più GTT per evitare qualsiasi operazione costosa potrebbe essere un buon approccio
Jack dice che prova topanswers.xyz il

@Jack Douglas psoug.org/reference/gtt.html ha una demo GTT Redo Generation che mostra una riduzione del 60% in redo tra una tabella fisica e una GTT per inserts. Questo corrisponde da vicino ai risultati che sto vedendo ed è migliore ma non buono come vorrei.
Leigh Riffel,

Quei test (riga per riga e nessun appendsuggerimento) non sono le condizioni ideali per ridurre la ripetizione: ho eseguito alcuni test per mostrare cosa intendo. Inserito come risposta perché non rientrano in un commento
Jack dice di provare topanswers.xyz il

Risposte:


5

Questo ha lo scopo di dimostrare l'uso ripetuto di varie insertoperazioni anziché rispondere all'intera domanda. I risultati sulla mia istanza da 10 g non sono deterministici al 100%, ma il quadro generale è rimasto lo stesso ogni volta che mi sono imbattuto.

Per le tabelle heap, non so perché il insert /*+ append */generato più rifare.

banco di prova:

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

test:

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

risultato:

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                   

Hai ragione ovviamente. Avrei dovuto prenderlo nei loro test. Lo proverò.
Leigh Riffel,

6

Buona domanda. Ho "risolto" questo problema per la mia situazione qualche tempo fa rendendo le MV e tutti gli indici su di esse NOLOGGING. La mia situazione non aveva senso: stavo comunque aggiornando completamente la vista, perché avrei dovuto rifare?


1
Potrebbe essere necessario anche ATOMIC_REFRESH = false (su 10 g e oltre). Non sei sicuro di quali siano le implicazioni per qualsiasi database di standby o ripristino con i log di archivio?
Jack dice di provare topanswers.xyz il

Eseguo uno standby logico e fisico sul database con cui l'ho fatto. Nessun problema lì. Ho riscontrato un problema con la creazione di copie DB: devo leggere le mie note, ma a volte ho riscontrato un errore durante l'esecuzione del ripristino su un tablespace con tabelle di nologging. Ho letto consigli per creare un tablespace riservato a tabelle / indici non blog per evitare tali problemi. Ho capito come risolverlo però.
DCookie,

@ Jack, credo di dover usare un aggiornamento non atomico.
DCookie,

Hmmm, se uso una vista materializzata standard, deve eseguire un aggiornamento atomico, quindi non funzionerà per me. Qualcun altro potrebbe trovarlo utile, quindi è ancora una buona risposta.
Leigh Riffel,

Perché ha bisogno di un aggiornamento atomico? A quanto ho capito, l'impostazione su false influisce solo su un aggiornamento COMPLETO. Vedi questo post di asktom: asktom.oracle.com/pls/apex/…
DCookie,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.