2016-06-21 84 views
0

我的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數據庫。我已經將這添加到了我的問題中。 –

回答

1

你認爲使用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ß - 對,對不起。沒有你的表,所以我不能測試代碼。 –