Включение parallel для index range scan и создания констрейнтов


Сегодня нужно было ускорить большую разовую выгрузку(вообще был "insert/*+append*/ select", но это не суть важно в данном контексте): большая не секционированная таблица, достаточно хорошая селективность по индексу( ~1.2%), больше 95% времени идет на lookup в таблицу из индекса. Один только индекс размером 44ГБ...

Изначальный запрос был вида:
select t_big.*
from t_big
where t_big.a=:a
Естественно, сразу захотелось распараллелить, но index range scan не идет в параллели, поэтому пришлось прибегнуть к небольшому ухищрению, которое позволило ускорить выполнение более чем в 13 раз при установке DOP в 16!

Метод прост: т.к.вычитка из индекса достаточно быстрая, то просто читаем и материализуем rowid через IRS, и затем уже в параллели идем к таблице через TABLE ACCESS BY USER ROWID.

Окончательный запрос:
with rids as(
            select--+ materialize
               rowid rid
            from t_big t1
            where t1.a=:a
)
select/*+ use_nl(rids t_big) */ t_big.*
from t_big, rids
where t_big.rowid=rids.rid

Создание констрейнтов в параллели:
По умолчанию при создании констрейнтов они валидируются не распараллеливаясь, что существенно замедляет процесс. Особенно учитывая, что обычно это происходит в технологические перерывы и ресурсов полно.. Решается же проблема просто: создавать их нужно с enable novalidate, и лишь затем отдельно включать enable validate:
alter table t1 
   add constraint fk_t1
   foreign key(a)
   references t2(a)
   enable novalidate;
alter table t1 
   modify constraint fk_t1
   enable validate;
UPD: Исправил на enable novalidate, т.к. как правильно заметил Тимур c disable не будет работать с unique и foreign key, а будет только для check constraints.

Comments

Отправить комментарий