Медленный триггер T-SQL - PullRequest
0 голосов
/ 21 января 2011

У меня есть 2 таблицы «Вектор» и «ВекторЭлемент».Вектор имеет много элементов, поэтому существует отношение внешнего ключа между Vector и VectorElement с каскадным удалением.
Vector имеет поле VectorSize, которое содержит номер количества связанных записей в VectorElement.
Очевидно, что это поле является избыточным, ноон оптимизирует производительность и делает наши запросы простыми, поскольку нас часто интересует количество элементов в векторе.
В VectorElement имеется триггер, который обновляет поле VectorSize в Vector.Этот триггер работает, но работает очень медленно, когда многие Векторные записи удаляются или вставляются в одну транзакцию.
Когда Векторы удаляются, каскадное удаление удаляет VectorElements, после чего срабатывает триггер.Теперь триггер обновляет векторную запись, которая будет удалена, что может вызвать некоторые проблемы, но это также происходит со вставками.

Вот триггер:

CREATE TRIGGER [TFact].[AfterDeleteInsertVectorElement] 
   ON  [TFact].[VectorElement] 
   AFTER DELETE, INSERT
AS 
BEGIN
    SET NOCOUNT ON;

  WITH cteChangedVectors AS
  ( 
      SELECT DISTINCT i.VectorId 
      FROM inserted i
      UNION 
      SELECT DISTINCT i.VectorId 
      FROM deleted i
  )

    UPDATE 
        TFact.Vector
    SET 
        VectorSize = x.size
    FROM 
        Vector v
    JOIN
        (SELECT VectorId, COUNT(*) as size FROM TFact.VectorElement GROUP BY VectorId) x
        ON v.Id = x.VectorId
    JOIN cteChangedVectors chg ON chg.VectorId = v.Id

END

Ответы [ 4 ]

1 голос
/ 22 января 2011

Попробуйте отследить общее количество векторных элементов с помощью индексированного представления.

См. http://technet.microsoft.com/en-us/library/cc917715.aspx#XSLTsection124121120120

SQL Server знает, как эффективно отслеживать агрегаты - это дешевле, чем запускать часть процедурного кода общего назначения при каждом вызове триггера.

Если вы работаете с SQL Server Enterprise, просто создайте представление, и ваши запросы будут динамически переписаны для их использования.

Что-то вроде ...

CREATE VIEW VectorSize AS
SELECT VectorId, COUNT(*)
FROM Vector NATURAL JOIN VectorElement
GROUP BY VectorId
GO
CREATE UNIQUE CLUSTERED INDEX VectorSizeInd ON VectorSize( VectorId )

SQL Server будет автоматически сохранять «твердую копию» размеров векторов в базе данных.

0 голосов
/ 21 января 2011

Это лучше?

UPDATE TFact.Vector
SET    VectorSize = x.size
FROM   Vector v
       inner join (
         select VectorId, count(*) size
         from   TFact.VectorElement
         where  VectorId in (select VectorId from cteChangedVectors)
         group by VectorId
       )x on x.VectorId = v.Id

Также убедитесь, что у вас есть индекс для TFact.VectorElement.VectorId, если размер базы данных большой.

С уважением GJ

0 голосов
/ 21 января 2011

Почему бы не вычислить значение "Delta" из вставленных и удаленных таблиц, а не пересчитать всю сумму по дочерней таблице?

 UPDATE
     V
SET
     VectorSize = VectorSize + Delta
FROM
     Vector V
         inner join
     (select VectorID,SUM(Deltas) as Delta from
          (select VectorID,1 as Deltas from inserted union all
           select VectorID,-1 from deleted) t
     group by VectorID
     ) u
         on
            V.VectorID = u.VectorID
0 голосов
/ 21 января 2011

SQL выглядит сложным. А если ожидаешь больших наборов, то лечи отдельно

IF EXISTS (SELECT * FROM DELETED)
    UPDATE 
        V
    SET 
        VectorSize = x.size
    FROM 
        Vector V
        JOIN
        (SELECT
             VectorId, COUNT(*) as size
        FROM
             DELETED
        GROUP BY
             VectorId
         ) x
        ON v.Id = x.VectorId
ELSE
    UPDATE 
        V
    SET 
        VectorSize = x.size
    FROM 
        Vector V
        JOIN
        (SELECT
             VectorId, COUNT(*) as size
        FROM
             INSERTED
        GROUP BY
             VectorId
         ) x
        ON v.Id = x.VectorId
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...