我已经对这种情况进行了基准测试,并得出结论:添加一个触发器可能会导致显着的性能损失,很可能是由于 PL/SQL 上下文切换引起的。在我的基准测试中,这种损失可以达到 8 倍。然而,添加第二个“兼容”的触发器就不再有任何显著影响了。所谓“兼容”,是指两个触发器始终以相同的顺序在同一事件中触发。
因此,我得出结论:所有触发器最有可能只需要执行一次 SQL -> PL/SQL
上下文切换。
以下是基准测试过程:
创建表格
CREATE TABLE test(
id number(38) not null,
uc varchar2(400) not null,
dc date not null,
um varchar2(400),
dm date,
data number(38)
);
... 和序列
CREATE SEQUENCE s_test;
典型的触发器设置ID、创建/修改用户和日期
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;
结果
另一个“兼容”的触发器(执行顺序无关)
(注:此处为标题,无需翻译)
CREATE OR REPLACE TRIGGER t_test_other BEFORE INSERT OR UPDATE
ON test
FOR EACH ROW
BEGIN
:new.data := 42;
END t_test_other;
另一个测试脚本的结果
禁用触发器
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;
结果