Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Konsolidieren Sie mehrere Oracle-Trigger. Auswirkungen auf die Leistung?

Ich habe diese Situation nun einem Benchmarking unterzogen und bin zu dem Schluss gekommen, dass beim Hinzufügen von 1 Trigger höchstwahrscheinlich ein erheblicher Leistungsverlust aufgrund von PL/SQL-Kontextwechseln auftritt. Der Verlust beträgt in meinem Benchmark Faktor 8. Das Hinzufügen eines zweiten "kompatiblen" Auslösers hat jedoch keine signifikanten Auswirkungen mehr. Mit "kompatibel" meine ich, dass beide Trigger immer beim selben Ereignis in beliebiger Reihenfolge ausgelöst werden.

Daraus schließe ich, dass es höchstwahrscheinlich nur 1 SQL -> PL/SQL gibt Kontextwechsel für alle Trigger

Hier ist der Benchmark:

Erstelle eine Tabelle

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

... und eine Sequenz

CREATE SEQUENCE s_test;

Eine typische Trigger-Einstellungs-ID, Benutzer/Datum der Erstellung/Änderung

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;

Fügen Sie 1000, 10000, 100000 Datensätze ein

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;

Ergebnisse

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

Ein weiterer "kompatibler" Trigger (Ausführungsreihenfolge irrelevant)

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

Ergebnisse einer weiteren Ausführung des Testskripts

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

Trigger deaktivieren

alter trigger t_test disable;
alter trigger t_test_other disable;

Führen Sie ein etwas anderes Testskript aus

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;

Ergebnisse

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