Oracle触发器性能将降低

问题描述

给出以下触发器:

CREATE OR REPLACE TRIGGER TR_MY_TRG_NAME
    AFTER UPDATE OF COL_A,COL_B,COL_C ON T_MY_TABLE_Y
    FOR EACH ROW
BEGIN
    UPDATE T_MY_TABLE_X X
        SET 
        X.COL_A = :NEW.COL_A,X.COL_B = :NEW.COL_B,X.COL_C = :NEW.COL_C
        WHERE
            X.ID = :NEW.ID;
END;

...并在T_MY_TABLE_Y中给出了200万条现有记录。

问题: 如果我的应用更改了所有2条mio记录(例如COL_A),那么在没有触发器的情况下,它会运行2-3分钟,而在使用触发器的情况下,则需要40分钟。

问题: 我可以尝试一些替代方法吗?

解决方法

另一种方法是在单个语句中更新T_MY_TABLE_X,而不必强制触发器触发200万行中的每行并(可能)执行上下文切换。

因此:当您更新T_MY_TABLE_Y时,请为UPDATE重用相同的T_MY_TABLE_X(必要时进行一些修改)。

,

我认为您可以通过分成三部分来更新DML的负载,以便为每个单独的列进行更新:

const firestore = firebase.firestore()
const ref = firestore.collection('messages').doc('foo')
ref.set({
    createdAt: firebase.firestore.FieldValue.serverTimestamp()
})

这样,Update可能不会在每次发生时都出现在每一列中。

此外,请确保CREATE OR REPLACE TRIGGER TR_MY_TRG_NAME AFTER UPDATE OF COL_A,COL_B,COL_C ON T_MY_TABLE_Y FOR EACH ROW BEGIN IF :NEW.COL_A != :OLD.COL_A THEN UPDATE T_MY_TABLE_X SET COL_A = :NEW.COL_A WHERE ID = :NEW.ID; END IF; IF :NEW.COL_B != :OLD.COL_B THEN UPDATE T_MY_TABLE_X SET COL_B = :NEW.COL_B WHERE ID = :NEW.ID; END IF; IF :NEW.COL_C != :OLD.COL_C THEN UPDATE T_MY_TABLE_X SET COL_C = :NEW.COL_C WHERE ID = :NEW.ID; END IF; END; 上有索引,最好是唯一索引。

,

我没有时间写出代码,但是我建议尝试使用一种概述方法,以创建一个ARRAYRECORD中的ID的程序包, COL_ACOL_BCOL_C

BEFORE语句触发器应实例化并初始化包和其中的数组,例如:

the_package.pr_init

ROW LEVEL触发器应仅将:NEW.ID,:NEW.COL_A,:NEW.COL_B,:NEW.COL_C写入包中的数组,例如:

the_package.pr_save ( :NEW.ID,:NEW.COL_A,:NEW.COL_B,:NEW.COL_C )

然后,AFTER语句触发器应该在驱动程序包内的数组上发出BULK UPDATE,并清除ARRAY,例如:

the_package.pr_do_update

这种方法的好处是,无论有多少行,您都只能执行一个附加的UPDATE语句。

该解决方案也包含在一个软件包中,尽管它在3个触发器之间展开,但是触发器代码本身将大大简化。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...