Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Consolide vários gatilhos Oracle. Algum impacto no desempenho?


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