2016-06-21 16 views
0

Ich habe ein kleines Leistungsproblem mit einem meiner Datenbank-Trigger in meiner MS-SQL Server 2014-Datenbank.Leistungsprobleme mit UPDATE in AFTER UPDATE Auslöser

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 

Was im Grunde tut es ist es die Lastupdated Spalte für alle Zeilen in eingefügt setzt und die DisturbedSince Spalte für eine Teilmenge der eingefügten Zeilen.

Schließlich werden die eingefügten Zeilen in eine Protokolltabelle kopiert. (Jede Änderung einer Zeile muss für zwei Tage gespeichert werden). Ältere Daten werden durch einen Wartungsauftrag gelöscht.

Da wir bis zu ~ 300 Zeilen pro Sekunde aktualisiert haben (Updates für Zeilen können zusammengelegt werden) Wir erstellen eine große Menge an Daten und rekursiven Updates.

Ich habe jetzt die INSTEAD OF UPDATE-Trigger gefunden, die das von meinem Trigger verursachte rekursive UPDATE-Problem zu lösen scheinen, aber ich müsste jede Zeile der eingefügten Tabelle nacheinander mit einer Update-Anweisung im Trigger verarbeiten.

Ich bin mir nicht sicher, ob das wirklich schneller ist. Hat jemand von euch eine Empfehlung?

Was ich wirklich brauche ist, die Datenzeilen zu optimieren/zu erweitern, bevor sie an die Tabelle gesendet werden. Gibt es einen Ansatz dafür?

z.B .: Etwas wie:

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 

und ein AFTER UPDATE TRIGGER mit der Speicherung der geänderten Daten in der History-Tabelle.

Vielen Dank für Anregungen.

Thomas

+1

Für welches RDBMS ist das? Trigger sind ** sehr ** anbieterspezifisch - bitte fügen Sie ein Tag hinzu, um anzugeben, ob Sie 'mysql',' postgresql', 'sql-server',' oracle' oder 'db2' verwenden - oder etwas ganz anderes. –

+0

"Ich müsste jede Zeile der eingefügten Tabelle nacheinander mit einer Update-Anweisung im Trigger verarbeiten." - Ähm, warum glaubst du das? –

+0

@Marc: Es ist eine MS-SQL Server 2014-Datenbank. Ich habe das zu meiner Frage hinzugefügt. –

Antwort

1

Du hast Recht zu denken, dass ein INSTEAD OF Trigger ist der richtige Weg eher zu gehen als ein AFTER Trigger, wenn Sie wollen, auch Daten in derselben Tabelle ändern.

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 

Sie werden bemerken, dass ich kombiniert haben sowohl die UPDATE s und die INSERT in der Historientabelle zu einer einzigen zusammengesetzten Anweisung:

Es wäre so etwas wie.

Sie werden auch bemerken, dass es etwas verwirrend, weil es zwei inserted s im Spiel hier - die inserted als Teil des Auslösers (aliased als i einige der Verwirrung zu umgehen) und die inserted als Teil der OUTPUT Klausel .

+0

Vielen Dank, ich werde es versuchen –

+0

Ich nehme an, dass in der DisturbedSince "update" sollte CASE WANN sein ... DANN .... SONST d.DisturedSince END? –

+0

@ ThomasVoß - ja, tut mir leid. Ich habe deine Tabellen nicht bekommen, daher kann ich den Code nicht testen. –