sql >> Database >  >> RDS >> Oracle

Consolideer verschillende Oracle-triggers. Enige prestatie-impact?

Ik heb deze situatie nu gebenchmarkt en ik kwam tot de conclusie dat er een aanzienlijk prestatieverlies is, hoogstwaarschijnlijk als gevolg van PL/SQL-context-switches, bij het toevoegen van 1 trigger. Het verlies is met factor 8 in mijn benchmark. Het toevoegen van een tweede "compatibele" trigger heeft echter geen significante impact meer. Met "compatibel" bedoel ik dat beide triggers altijd op dezelfde gebeurtenis in willekeurige volgorde worden geactiveerd.

Dus ik concludeer dat er hoogstwaarschijnlijk maar 1 SQL -> PL/SQL is contextschakelaar voor alle triggers

Dit is de maatstaf:

Maak een tafel

-- 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)
);

... en een reeks

CREATE SEQUENCE s_test;

Een typische triggerinstelling-ID, aanmaak/wijziging gebruiker/datum

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 records invoegen

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;

Resultaten

-- ------------------------------------
-- +000000000 00:00:00.086603000
-- +000000000 00:00:00.844333000
-- +000000000 00:00:08.429186000
-- ------------------------------------

Nog een "compatibele" trigger (uitvoeringsvolgorde niet relevant)

CREATE OR REPLACE TRIGGER t_test_other BEFORE INSERT OR UPDATE
  ON test
  FOR EACH ROW
BEGIN
  :new.data := 42;
END t_test_other;

Resultaten van een andere uitvoering van het testscript

-- ------------------------------------
-- +000000000 00:00:00.088551000
-- +000000000 00:00:00.876028000
-- +000000000 00:00:08.731345000
-- ------------------------------------

Deactiveer triggers

alter trigger t_test disable;
alter trigger t_test_other disable;

Voer een iets ander testscript uit

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;

Resultaten

-- ------------------------------------
-- +000000000 00:00:00.012712000
-- +000000000 00:00:00.104903000
-- +000000000 00:00:01.043984000
-- ------------------------------------


  1. LoadError probeert MySQL te gebruiken met Ruby on Rails in Windows, RubyMine IDE

  2. Oracle:Combineer meerdere resultaten in een subquery tot één door komma's gescheiden waarde

  3. Meerdere ongewenste records in Groeperen op clausule in Postgress

  4. Regex gebruiken met LIKE om eerst alfabetten te sorteren en daarna symbolen SQL