Какие преимущества в производительности для консолидации триггеров SQL Server? - PullRequest
1 голос
/ 07 февраля 2012

У меня есть одна таблица SQL Server с 10 различными триггерами, которые срабатывают при одной и той же INSERT и UPDATE.

Есть ли какое-либо преимущество в производительности для объединения SQL внутри 10 триггеров в один триггер?

Один консолидированный триггер будет делать то же самое, что и 10 разных триггеров, но вместо 10. будет срабатывать только один триггер.

Спасибо!

Обновление: спасибо за отличный отзыв. Я обновил свой вопрос, чтобы указать, что я задаюсь вопросом о преимуществах производительности. Я не думал о преимуществе «абсолютного контроля над порядком». Я знаю, что в какой-то момент эти различные триггеры должны быть подвергнуты рефакторингу, но мне интересно больше о производительности одного из множества триггеров.

Ответы [ 4 ]

4 голосов
/ 07 февраля 2012

Основное преимущество, которое я вижу, заключается в том, что вы будете иметь полный контроль над порядком выполнения, которого у вас нет сейчас.

Я мог бы предложить гибридный подход: 1 триггер, который вызывает 10 хранимых процедур, каждая из которых содержит логику одного из существующих триггеров.

2 голосов
/ 07 февраля 2012

Консолидация триггеров может значительно повысить производительность. Например, рассмотрим следующую таблицу, два триггера и обновление:

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 мс ЦП и 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;

Это же обновление работает вдвое быстрее. Большой сюрприз. ;)

2 голосов
/ 07 февраля 2012

Я согласен с Джо. Объединяя в один триггер, вы получаете:

  • полный контроль над заказом
  • Лучшая видимость всех операций в одном месте

Вы также возможно сможете более четко видеть места, где часть этой логики может быть скомбинирована, и с большим фрагментом кода может вызвать мотивацию для ее очистки. 10 триггеров звучит как ужасно много. Какова тенденция для операций, которые выполняются в каждом из триггеров? Это аудит, обновление итогов и т. Д.? Я уверен, что есть некоторые вещи, которые могут быть обработаны лучшей предварительной логикой (например, хранимые процедуры, которые обрабатывают начальные операции вставки / обновления, вычисляемые столбцы, даже индексированные представления для предотвращения необходимости выполнения вычислений после DML). *

0 голосов
/ 07 февраля 2012

Было бы намного больше SP для вставки, обновления и удаления триггеров, кроме того, что я согласен с @Joe Stefanelli. Не могу понять, почему вы так или иначе получите заметное повышение производительности.

10 триггеров, дрожь ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...