Now I am comparing this situation, and I have come to the conclusion that a significant performance loss is most likely due to PL / SQL context switches when adding 1 trigger. Loss of 8 times compared with my figure. However, adding a second “compatible” trigger has no significant effect. By "compatible" I mean that both triggers always fire in the same event in any order.
So, I will conclude that for all triggers, only 1 SQL -> PL/SQL most likely SQL -> PL/SQL context switch
Here's the benchmark:
Create table
-- 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) );
... and sequence
CREATE SEQUENCE s_test;
Typical trigger installation identifier, create / modify user / date
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;
Insert 1000, 10000, 100000 records
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;
results
-- ------------------------------------ -- +000000000 00:00:00.086603000 -- +000000000 00:00:00.844333000 -- +000000000 00:00:08.429186000 -- ------------------------------------
Another "compatible" trigger (execution order does not matter)
CREATE OR REPLACE TRIGGER t_test_other BEFORE INSERT OR UPDATE ON test FOR EACH ROW BEGIN :new.data := 42; END t_test_other;
Results of another script test run
-- ------------------------------------ -- +000000000 00:00:00.088551000 -- +000000000 00:00:00.876028000 -- +000000000 00:00:08.731345000 -- ------------------------------------
Deactivate Triggers
alter trigger t_test disable; alter trigger t_test_other disable;
Run a slightly different test script
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;
results
-- ------------------------------------ -- +000000000 00:00:00.012712000 -- +000000000 00:00:00.104903000 -- +000000000 00:00:01.043984000 -- ------------------------------------