2012-02-06 47 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