Сега направих сравнителен анализ на тази ситуация и стигнах до заключението, че има значителна загуба на производителност, най-вероятно поради превключване на контекста на PL/SQL, при добавяне на 1 тригер. Загубата е с фактор 8 в моя бенчмарк. Добавянето на втори „съвместим“ тригер обаче вече няма значително въздействие. Под „съвместим“ имам предвид и двата тригера винаги да се задействат при едно и също събитие в произволен ред.
Така че заключавам, че най-вероятно има само 1 SQL -> PL/SQL
превключвател на контекст за всички тригери
Ето бенчмарка:
Създаване на таблица
-- 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)
);
... и последователност
CREATE SEQUENCE s_test;
Типичен идентификатор на настройка на тригер, потребител/дата на създаване/модифициране
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;
Вмъкване на 1000, 10000, 100000 записа
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;
Резултати
-- ------------------------------------
-- +000000000 00:00:00.086603000
-- +000000000 00:00:00.844333000
-- +000000000 00:00:08.429186000
-- ------------------------------------
Друг „съвместим“ тригер (редът на изпълнение е без значение)
CREATE OR REPLACE TRIGGER t_test_other BEFORE INSERT OR UPDATE
ON test
FOR EACH ROW
BEGIN
:new.data := 42;
END t_test_other;
Резултати от друго изпълнение на тестовия скрипт
-- ------------------------------------
-- +000000000 00:00:00.088551000
-- +000000000 00:00:00.876028000
-- +000000000 00:00:08.731345000
-- ------------------------------------
Деактивирайте тригерите
alter trigger t_test disable;
alter trigger t_test_other disable;
Изпълнете малко по-различен тестов скрипт
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;
Резултати
-- ------------------------------------
-- +000000000 00:00:00.012712000
-- +000000000 00:00:00.104903000
-- +000000000 00:00:01.043984000
-- ------------------------------------