Консолидация нескольких триггеров Oracle. Влияние на производительность?
большинство наших таблиц имеют один BEFORE INSERT OR UPDATE
триггер, чтобы установить ID BEFORE INSERT
и установить создание / изменение пользователей / даты BEFORE INSERT OR UPDATE
.
есть несколько таблиц с дополнительными триггерами, которые были отделены от предыдущего, чтобы сделать их намерение более ясным. Кроме того, эти дополнительные триггеры могут быть отключены независимо от предыдущего, который никогда не должен быть отключен.
в большинстве случаев, дополнительные триггеры и огонь BEFORE INSERT OR UPDATE
и порядок неважен, поскольку они охватывают разные столбцы / варианты использования. Так что в общем, они мог бы объединяются в отдельные триггеры.
есть ли какие-либо исследования о скорости вызова 1
или n
триггеры на таблице? Или это в значительной степени не имеет значения для однорядных вставок / обновлений? Другими словами, существует только 1 global SQL -> PL/SQL
переключатель контекста, или будет 1 переключатель контекста на триггер.
3 ответов
теперь я сравнил эту ситуацию, и я пришел к выводу, что существует значительная потеря производительности, скорее всего, из-за контекстных переключателей 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
-- ------------------------------------
Я знаю, что существует значительная разница в генерации повтора между триггерами без триггеров и одним триггером, но не о разнице между 1 и n триггерами. Однако я не могу себе представить, что нет хита, так как было бы больше переключения контекста между SQL и PL/SQL-движками.
Я бы предложил вам изучить влияние использования последовательности в триггере - при создании семени последовательности последовательность со значением кэша (Кэш указывает, сколько значений последовательности база данных предварительно распределяет и сохраняет в памяти для более быстрого доступа). Я испытал факторы, намного большие 8, связанные с последовательностями. В любом случае, чтобы сравнить влияние триггера с точки зрения переключения контекста, следует либо исключить использование последовательности для тест или учитывается при оценке результатов.