Oracle
 sql >> Base de données >  >> RDS >> Oracle

Consolidez plusieurs déclencheurs Oracle. Un impact sur les performances ?

J'ai maintenant comparé cette situation et je suis arrivé à la conclusion qu'il y a une perte de performances significative très probablement due aux changements de contexte PL/SQL, lors de l'ajout d'un déclencheur. La perte est d'un facteur 8 dans mon benchmark. Cependant, l'ajout d'un deuxième déclencheur "compatible" n'a plus d'impact significatif. Par "compatible", je veux dire que les deux déclencheurs se déclenchent toujours au même événement dans n'importe quel ordre.

Je conclus donc qu'il n'y a probablement qu'un seul SQL -> PL/SQL changement de contexte pour tous les déclencheurs

Voici la référence :

Créer un tableau

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

... et une séquence

CREATE SEQUENCE s_test;

Un ID de paramètre de déclencheur typique, un utilisateur/une date de création/modification

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;

Insérer 1000, 10000, 100000 enregistrements

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;

Résultats

-- ------------------------------------
-- +000000000 00:00:00.086603000
-- +000000000 00:00:00.844333000
-- +000000000 00:00:08.429186000
-- ------------------------------------

Un autre déclencheur "compatible" (ordre d'exécution non pertinent)

CREATE OR REPLACE TRIGGER t_test_other BEFORE INSERT OR UPDATE
  ON test
  FOR EACH ROW
BEGIN
  :new.data := 42;
END t_test_other;

Résultats d'une autre exécution du script de test

-- ------------------------------------
-- +000000000 00:00:00.088551000
-- +000000000 00:00:00.876028000
-- +000000000 00:00:08.731345000
-- ------------------------------------

Désactiver les déclencheurs

alter trigger t_test disable;
alter trigger t_test_other disable;

Exécutez un script de test légèrement différent

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;

Résultats

-- ------------------------------------
-- +000000000 00:00:00.012712000
-- +000000000 00:00:00.104903000
-- +000000000 00:00:01.043984000
-- ------------------------------------