更新后在更新后的性能问题触发器

问题描述:

我的MS-SQL Server 2014数据库中的一个数据库触发器有一个小的性能问题。更新后在更新后的性能问题触发器

CREATE TRIGGER [dbo].[TRG_T_TPM_Vehicle_Update] ON [dbo].[T_TPM_Vehicle] 
    AFTER UPDATE 
AS 
BEGIN 
-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with SELECT statements. 
SET NOCOUNT ON; 
UPDATE T_TPM_Vehicle SET LastUpdated = getdate() 
     WHERE Vehicle_Number IN (SELECT Vehicle_Number FROM inserted) 

UPDATE T_TPM_Vehicle SET [DisturbedSince] = getdate() 
     WHERE Vehicle_Number IN (SELECT Vehicle_Number FROM inserted WHERE inserted.Emergency_Stop = 1) 
     AND Vehicle_Number IN (SELECT Vehicle_Number FROM deleted WHERE deleted.Emergency_Stop = 0) 

INSERT INTO T_TPM_Vehicle_HistoricalData 
     ([Vehicle_Ref] 
     ,[Vehicle_Number] 
     ,[Vehicle_Type] 
     ,[Pos_X] 
     ,[Pos_Y] 
     ,[Alpha] 
     ,[LastAutoPos_X] 
     ,[LastAutoPos_Y] 
     ,[LastAutoAlpha] 
     ,[Automatic] 
     ,[Manual] 
     ,[Blocked] 
     ,[Loaded] 
     ,[Stoped] 
     ,[Emergency_Stop] 
     ,[User_Required] 
     ,[BatteryAlmostEmpty] 
     ,[BatteryEmpty] 
     ,[BatteryLevel] 
     ,[ChargingRelaisEnable] 
     ,[NavOK] 
     ,[PowerOn] 
     ,[Available] 
     ,[OperatingMinutes] 
     ,[UpdateOperatingMinutes] 
     ,[DataChangedByVIS] 
     ,[Blockingsreleased] 
     ,[Cancelled] 
     ,[ProductID] 
     ,[HUIdent1] 
     ,[HUIdent2] 
     ,[HUType] 
     ,[DisturbedSince]) 
SELECT inserted.[Vehicle_Ref] 
    ,inserted.[Vehicle_Number] 
    ,inserted.[Vehicle_Type] 
    ,inserted.[Pos_X] 
    ,inserted.[Pos_Y] 
    ,inserted.[Alpha] 
    ,inserted.[LastAutoPos_X] 
    ,inserted.[LastAutoPos_Y] 
    ,inserted.[LastAutoAlpha] 
    ,inserted.[Automatic] 
    ,inserted.[Manual] 
    ,inserted.[Blocked] 
    ,inserted.[Loaded] 
    ,inserted.[Stoped] 
    ,inserted.[Emergency_Stop] 
    ,inserted.[User_Required] 
    ,inserted.[BatteryAlmostEmpty] 
    ,inserted.[BatteryEmpty] 
    ,inserted.[BatteryLevel] 
    ,inserted.[ChargingRelaisEnable] 
    ,inserted.[NavOK] 
    ,inserted.[PowerOn] 
    ,inserted.[Available] 
    ,inserted.[OperatingMinutes] 
    ,inserted.[UpdateOperatingMinutes] 
    ,inserted.[DataChangedByVIS] 
    ,inserted.[Blockingsreleased] 
    ,inserted.[Cancelled] 
    ,inserted.[ProductID] 
    ,inserted.[HUIdent1] 
    ,inserted.[HUIdent2] 
    ,inserted.[HUType] 
    ,inserted.[DisturbedSince] 
FROM inserted 
END 

它通常做的是它设置在插入所有行和插入的行的子集的DisturbedSince列LASTUPDATED列。

最后插入的行被复制到历史记录表中。 (任何行上的每次更改都必须保存两天)。旧数据被维护作业删除。

由于我们每秒更新约300行(更新行可以一起批处理)我们创建了大量的数据和递归更新。

我现在发现INSTEAD OF UPDATE触发器似乎解决了由触发器引起的递归UPDATE问题,但是我必须用触发器中的更新语句逐个处理插入表的每一行。

我不确定这是否真的更快。你们中有人有推荐吗?

我真正需要的是在数据行被发送到表之前调整/扩展数据行。有没有办法呢?

例如: - 是这样的:

CREATE TRIGGER ... INSTEAD OF UPDATE 
AS 
BEGIN 
    UPDATE inserted SET LastUpdated = getdate() 
    UPDATE inserted SET DisturbedSince 
    WHERE Vehicle_Number IN (SELECT Vehicle_Number FROM inserted WHERE inserted.Emergency_Stop = 1) 
     AND Vehicle_Number IN (SELECT Vehicle_Number FROM deleted WHERE deleted.Emergency_Stop = 0) 
    "SAVE INSERTED" 
END 

,并与保存更改的数据的历史记录表格的AFTER UPDATE触发器。

谢谢你的任何建议。

托马斯

+1

哪个RDBMS是为了这个?触发器是**高度**特定于供应商的 - 请添加一个标签以指定您是使用'mysql','postgresql','sql-server','oracle'还是'db2' - 或者其他的东西。 –

+0

“我必须用触发器中的更新语句逐个处理插入表的每一行。” - 恩,你为什么这么相信? –

+0

@Marc:这是一个MS-SQL Server 2014数据库。我已经将这添加到了我的问题中。 –

你认为使用INSTEAD OF触发去,而不是一个AFTER触发正确的优先通行权,当你想在同一个表内更改数据也是如此。

这将是这样的:

CREATE TRIGGER [dbo].[TRG_T_TPM_Vehicle_Update] ON [dbo].[T_TPM_Vehicle] 
    INSTEAD OF UPDATE 
AS 
BEGIN 
-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with SELECT statements. 
SET NOCOUNT ON; 

UPDATE tgt 
SET 
    Vehicle_Ref = i.Vehicle_Ref, 
    Vehicle_Type = i.Vehicle_Type, 
    ... 
    LastUpdated = getdate(), 
    DisturbedSince = CASE WHEN i.Emergency_Stop=1 and d.Emergency_Stop=0 
        THEN getdate() ELSE d.DisturbedSince END 
OUTPUT 
    inserted.[Vehicle_Ref] 
    ,inserted.[Vehicle_Number] 
    ,inserted.[Vehicle_Type] 
    ... 
    ,inserted.[HUIdent2] 
    ,inserted.[HUType] 
    ,inserted.[DisturbedSince] 
INTO T_TPM_Vehicle_HistoricalData 
     ([Vehicle_Ref] 
     ,[Vehicle_Number] 
     ,[Vehicle_Type] 
     ... 
     ,[HUIdent2] 
     ,[HUType] 
     ,[DisturbedSince]) 
FROM 
    T_TPM_Vehcile tgt 
     inner join 
    inserted i 
     on 
     tgt.Vehicle_Number = i.Vehicle_Number 
     inner join 
    deleted d 
     on 
     tgt.Vehicle_Number = d.Vehicle_Number 

你会注意到,我已经合并双方UPDATE S和INSERT到历史表成一个单一的复合语句。

你还会注意到它的稍显混乱,因为有两个inserted S IN游戏在这里 - 在inserted作为触发(别名为i回避一些混乱)的一部分,inserted作为OUTPUT子句的一部分。

+0

谢谢我会试一试 –

+0

我认为在DisturbedSince“更新”中应该是CASE WHEN ... THEN .... ELSE d.DisturbedSince END? –

+0

@ThomasVoß - 对,对不起。没有你的表,所以我不能测试代码。 –