Лимитный повтор для материализованного представления, полное обновление или ручной эквивалент

10

Журнал с материализованным представлением (MV) может использоваться для того, чтобы позволить MV быстро обновлять данные, изменяя только измененные данные. Однако различные условия не позволяют MV использовать журнал и поэтому требуют полного обновления. Oracle реализовал полное атомарное обновление в виде удаления и вставки каждой записи. Это происходит даже в том случае, если в конечном итоге данные не изменяются.

Есть ли способ сделать эту репликацию разумной в отношении генерации повторов ? MERGE, за которым следует DELETE, запрашивает источник дважды. Стоит ли массово собирать данные, чтобы выполнить BULK MERGE и DELETE? Есть ли способ лучше?

Обновить:

Я исследовал использование глобальной временной таблицы в качестве промежуточной области. Хотя они используют меньше половины повторов, они все равно используют много.

Ли Риффель
источник
Вы можете опубликовать код gtt? GTT не генерируют повтор напрямую, но они генерируют отмену - и отмена генерирует повтор. insertops генерируют гораздо меньше откатов, чем deleteили updateops (практически ни одного). Хорошим подходом может быть наличие нескольких gtts, чтобы избежать дорогостоящих операций
Джек говорит, что попробуйте topanswers.xyz
@Jack Douglas psoug.org/reference/gtt.html имеет демонстрацию GTo Redo Generation, демонстрирующую 60% -ное уменьшение повторов между физической таблицей и GTT для inserts. Это близко соответствует результатам, которые я вижу, и лучше, но не так хорошо, как хотелось бы.
Ли Риффель
Эти тесты (построчно и без appendподсказок) не являются идеальными условиями для уменьшения повторения - я провел несколько тестов, чтобы показать, что я имею в виду. Опубликовано в качестве ответа, потому что они не вписываются в комментарий
Джек говорит попробуйте topanswers.xyz

Ответы:

5

Это просто предназначено для демонстрации повторного использования различных insertопераций, а не для ответа на весь вопрос. Результаты на моем 10g экземпляре не являются на 100% детерминированными, но общая картина оставалась неизменной каждый раз, когда я пробежал.

Для кучи таблиц я не знаю, почему insert /*+ append */генерируется больше повторов.

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

контрольная работа:

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                   
Джек говорит, попробуйте topanswers.xyz
источник
Вы правы конечно. Я должен был поймать это в своих тестах. Я попробую.
Ли Риффель
6

Хороший вопрос. Я "решил" эту проблему для моей ситуации некоторое время назад, делая MV и любые индексы на них NOLOGGING. Не было никакого смысла в моей ситуации - в любом случае я делал полное обновление представления, зачем мне повторять?

DCookie
источник
1
Вам также может понадобиться ATOMIC_REFRESH = false (для 10g и выше). Не уверены, каковы последствия для любой резервной базы данных или восстановления с архивными журналами?
Джек говорит, попробуйте topanswers.xyz
Я запускаю логический и физический резерв в базе данных, с которой я это сделал. Там нет проблем. Я столкнулся с проблемой создания копий БД - мне приходилось просматривать мои заметки, но была ошибка, которая иногда возникала при выполнении восстановления табличного пространства с таблицами записей. Я прочитал рекомендации по созданию табличного пространства, зарезервированного для таблиц / индексов, которые не являются журналами, чтобы избежать таких проблем. Я выяснил, как решить это все же.
DCookie
@ Джек, я считаю, что мне пришлось использовать не атомарное обновление.
DCookie
Хммм, если я использую стандартное материализованное представление, оно должно сделать атомное обновление, так что это не будет работать для меня. Кто-то может найти это полезным, так что это все еще хороший ответ.
Ли Риффель
Зачем нужно атомное обновление? Насколько я понимаю, установка в false только влияет на полное обновление. См. Этот пост Asktom: asktom.oracle.com/pls/apex/…
DCookie