Agora fiz o benchmark dessa situação e cheguei à conclusão de que há uma perda significativa de desempenho provavelmente devido a alternâncias de contexto PL/SQL, ao adicionar 1 gatilho. A perda é pelo fator 8 no meu benchmark. Adicionar um segundo gatilho "compatível", no entanto, não tem mais nenhum impacto significativo. Por "compatível", quero dizer que ambos os gatilhos sempre disparam no mesmo evento em qualquer ordem.
Então, estou concluindo que provavelmente há apenas 1
SQL -> PL/SQL
mudança de contexto para todos os gatilhos Aqui está a referência:
Criar uma tabela
-- A typical table with primary key, creation/modification user/date, and
-- other data columns
CREATE TABLE test(
id number(38) not null, -- pk
uc varchar2(400) not null, -- creation user
dc date not null, -- creation date
um varchar2(400), -- modification user
dm date, -- modification date
data number(38)
);
... e uma sequência
CREATE SEQUENCE s_test;
Um ID típico de configuração de acionador, usuário/data de criação/modificação
CREATE OR REPLACE TRIGGER t_test BEFORE INSERT OR UPDATE
ON test
FOR EACH ROW
BEGIN
IF inserting THEN
SELECT s_test.nextval INTO :new.id FROM dual;
:new.uc := USER;
:new.dc := SYSDATE;
:new.um := NULL;
:new.dm := NULL;
END IF;
IF updating THEN
:new.um := USER;
:new.dm := SYSDATE;
:new.uc := :old.uc;
:new.dc := :old.dc;
END IF;
END t_test;
Inserir 1.000, 10.000, 100.000 registros
declare
procedure run (limit number) is
t timestamp;
begin
t := systimestamp;
insert into test (data)
select level from dual connect by level < limit;
dbms_output.put_line(to_char(systimestamp - t));
rollback;
end;
begin
run(1000);
run(10000);
run(100000);
end;
Resultados
-- ------------------------------------
-- +000000000 00:00:00.086603000
-- +000000000 00:00:00.844333000
-- +000000000 00:00:08.429186000
-- ------------------------------------
Outro gatilho "compatível" (ordem de execução irrelevante)
CREATE OR REPLACE TRIGGER t_test_other BEFORE INSERT OR UPDATE
ON test
FOR EACH ROW
BEGIN
:new.data := 42;
END t_test_other;
Resultados de outra execução do script de teste
-- ------------------------------------
-- +000000000 00:00:00.088551000
-- +000000000 00:00:00.876028000
-- +000000000 00:00:08.731345000
-- ------------------------------------
Desativar acionadores
alter trigger t_test disable;
alter trigger t_test_other disable;
Execute um script de teste ligeiramente diferente
declare
procedure run (limit number) is
t timestamp;
begin
t := systimestamp;
insert into test (id, uc, dc, data)
select s_test.nextval, user, sysdate, level from dual
connect by level < limit;
dbms_output.put_line(to_char(systimestamp - t));
rollback;
end;
begin
run(1000);
run(10000);
run(100000);
end;
Resultados
-- ------------------------------------
-- +000000000 00:00:00.012712000
-- +000000000 00:00:00.104903000
-- +000000000 00:00:01.043984000
-- ------------------------------------