Объедините несколько триггеров Oracle.Какое влияние на производительность? - PullRequest
6 голосов
/ 20 декабря 2011

Большинство наших таблиц имеют один триггер BEFORE INSERT OR UPDATE, чтобы установить идентификаторы BEFORE INSERT и установить пользователей / даты создания / изменения BEFORE INSERT OR UPDATE.

Есть пара таблиц с дополнительными триггерами, которые были отделены от предыдущей, чтобы сделать их намерение более ясным. Кроме того, эти дополнительные триггеры могут быть отключены независимо от предыдущего, что никогда не должно отключаться.

В большинстве случаев дополнительные триггеры также запускают BEFORE INSERT OR UPDATE, и порядок не имеет значения, поскольку они охватывают разные столбцы / варианты использования. Поэтому, как правило, они могут объединяться в отдельные триггеры.

Существуют ли исследования скорости вызова триггеров 1 или n на столе? Или это в значительной степени не имеет значения для однорядных вставок / обновлений? Другими словами, существует только 1 глобальный SQL -> PL/SQL переключатель контекста или будет 1 переключатель контекста на триггер.

Ответы [ 3 ]

5 голосов
/ 22 декабря 2011

Я сейчас провел сравнительный анализ этой ситуации и пришел к выводу, что при добавлении 1 триггера происходит значительное снижение производительности, скорее всего, из-за переключений контекста PL / SQL.В моем тесте потеря в 8 раз.Однако добавление второго «совместимого» триггера уже не оказывает существенного влияния.Под «совместимым» я подразумеваю, что оба триггера всегда запускаются в одном и том же событии в любом порядке.

Итак, я заключаю, что, скорее всего, для всех триггеров

* 1005 существует только 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 голос
/ 07 сентября 2013

Я бы посоветовал вам изучить влияние использования последовательности в триггере - при создании последовательности начального числа последовательность со значением кэша (CACHE указывает, сколько значений последовательности база данных предварительно распределяет и хранит в памяти для более быстрого доступа). Я испытал факторы гораздо больше, чем 8, связанных с последовательностями. В любом случае, чтобы сравнить влияние триггера в терминах переключения контекста, использование последовательности следует либо исключить для теста, либо принять во внимание при оценке результатов.

1 голос
/ 20 декабря 2011

Я знаю, что существует значительная разница в генерации повторов между отсутствием триггеров и одним триггером, но не в разнице между 1 и n триггерами.Однако я не могу себе представить, что хита нет, так как было бы больше переключения контекста между механизмами SQL и PL / SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...