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