sql >> データベース >  >> RDS >> Oracle

複数のOracleトリガーを統合します。パフォーマンスへの影響はありますか?

    この状況のベンチマークを行ったところ、トリガーを1つ追加すると、PL/SQLコンテキストスイッチが原因でパフォーマンスが大幅に低下する可能性が高いという結論に達しました。私のベンチマークでは、損失は第8因子によるものです。ただし、2番目の「互換性のある」トリガーを追加しても、大きな影響はありません。 「互換性がある」とは、両方のトリガーが常に同じイベントで任意の順序で発生することを意味します。

    したがって、SQL -> PL/SQLはおそらく1つしかないと結論付けています。 すべてのトリガーのコンテキストスイッチ

    ベンチマークは次のとおりです。

    テーブルを作成する

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

    一般的なトリガー設定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;
    

    結果

    -- ------------------------------------
    -- +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. OracleのCheckステートメントでのサブクエリの使用

    2. 条件に基づいてクエリを更新する

    3. 配列を使用したPDO更新テーブル

    4. MySQLは2つの#/複数のペアの#の間で文字列を取得します