2012-02-06 42 views
1

我有一個單一的SQL Server表,10個不同的觸發器在相同的INSERT和UPDATE上觸發。合併SQL Server觸發器的任何性能優勢?

將10個觸發器中的SQL整合到一個觸發器中是否有任何性能優勢?

單一的合併觸發會做同樣的事情,10個不同的觸發,但只有一個觸發器將被解僱10

感謝,而不是!

更新:感謝您的好評。我更新了我的問題,表明我對性能優勢感到疑惑。我沒有想到「絕對控制訂單」的優勢。我知道這些不同的觸發器應該在某個時候被重構,但我更想知道一個觸發器與多個觸發器的性能。

+0

這是否意味着你在'INSERTED'和'DELETED'僞表之間也有10個不同的連接?尤其是你可能只加入一次,尤其是因爲它們沒有編入索引。 – 2012-02-06 22:43:32

+0

如果沒有基準測試,我不會回答。你可以發佈你的觸發器在做什麼? – 2012-02-07 02:05:24

回答

2

合併觸發器可以提高性能。例如,考慮下表,兩個觸發器和一個更新:

CREATE TABLE dbo.TriggerTest(ID INT NOT NULL PRIMARY KEY, 
s INT NOT NULL) 
GO 
INSERT INTO dbo.TriggerTest(ID, s) 
SELECT n, 1 FROM dbo.Numbers 
WHERE n BETWEEN 1 AND 100000; 
GO 

CREATE TRIGGER TriggerTestNoSignChange 
ON dbo.TriggerTest 
AFTER UPDATE 
AS 
BEGIN 
    IF EXISTS(SELECT * FROM INSERTED AS i JOIN DELETED AS d 
    ON i.id = d.id WHERE sign(i.s)*sign(d.s)<0) 
    BEGIN 
     RAISERROR('s cannot change sign', 16, 1); 
     ROLLBACK ; 
    END 
END 
GO 

CREATE TRIGGER TriggerTestNoBigChange 
ON dbo.TriggerTest 
AFTER UPDATE 
AS 
BEGIN 
    IF EXISTS(SELECT * FROM INSERTED AS i JOIN DELETED AS d 
    ON i.id = d.id WHERE ABS(i.s - d.s)>5) 
    BEGIN 
     RAISERROR('s cannot change by more than 5', 16, 1); 
     ROLLBACK ; 
    END 
END 
GO 


UPDATE dbo.TriggerTest SET s=s+1 
WHERE ID BETWEEN 1 AND 1000; 

此更新使用1671毫秒CPU和4M讀取。讓我們合併兩個觸發器並重新運行更新:

DROP TRIGGER TriggerTestNoSignChange; 
DROP TRIGGER TriggerTestNoBigChange; 
GO 
CREATE TRIGGER TriggerTestNoBigChangeOrSignChange 
ON dbo.TriggerTest 
AFTER UPDATE 
AS 
BEGIN 
    IF EXISTS(SELECT * FROM INSERTED AS i JOIN DELETED AS d 
    ON i.id = d.id WHERE sign(i.s)*sign(d.s)<0 OR ABS(i.s - d.s)>5) 
    BEGIN 
     RAISERROR('s cannot change sign or change by more than 5', 16, 1); 
     ROLLBACK ; 
    END 
END 
GO 


UPDATE dbo.TriggerTest SET s=s+1 
WHERE ID BETWEEN 1 AND 1000; 

相同的更新運行速度快兩倍。大驚喜。 ;)

+0

一個非常直接的解釋。謝謝。我的大多數觸發器不兼容,無法像您所做的那樣利用相同的INSERT或UPDATE語句,但我可以使用您的一些解決方案和Aaron的一些解決方案(調用存儲過程)來處理所有這些觸發器都會爲AFTER INSERT和AFTER UPDATE事件觸發。 – Kuyenda 2012-02-07 20:38:46

4

我看到的主要優點是您可以完全控制執行的順序,而您現在沒有這個順序。

我可能會提出一種混合方法:1個觸發器調用10個存儲過程,每個存儲過程封裝一個現有觸發器的邏輯。

0

除了我同意@Joe Stefanelli之外,還會有更多的SP來插入和更新並刪除觸發器。看不出爲什麼你會以這種方式獲得明顯的性能提升。

10觸發器,不寒而慄...

2

我同意喬。通過結合到一個觸發你:

  • 完全控制順序
  • 更好地瞭解所有的操作都必須在一個地方

您還可以可能能夠更清楚地看到可以將這些邏輯中的某些邏輯組合起來的地方,並且用更大的代碼片段可能能夠調用動機來清理它。 10個觸發器聽起來非常糟糕。每個觸發器正在執行的操作的趨勢是什麼?它是審計,更新某處的總計等?我確信有一些事情可以通過更好的前端邏輯(例如處理初始插入/更新操作的存儲過程,計算列,甚至索引視圖來防止需要執行DML之後的計算)來處理。

+0

以上都是。而不是重構這個較舊的數據庫,我們正在研究它。我需要再添加一個觸發器來促進將數據複製到其他地方的過程,並且想知道這個新觸發器是否會成爲打破駱駝背的秸稈。 – Kuyenda 2012-02-06 23:09:33