【发布时间】:2013-05-17 16:28:01
【问题描述】:
我正在编写一个触发器来将一个表的记录计数存储为另一个表中的列,以加快大型数据库上的一些报告查询。
这是我到目前为止所得到的,它在删除时工作正常,但我还需要它在插入时工作。我需要使用单独的触发器吗?另外,是否有必要使用游标,还是有更有效的方法?
谢谢!
ALTER TRIGGER [dbo].[updateSourceTotals]
ON [dbo].imports
AFTER INSERT, DELETE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sourceId int;
DECLARE deleteCursor CURSOR FOR SELECT DISTINCT sourceId FROM deleted
OPEN deleteCursor
FETCH NEXT FROM deleteCursor INTO @sourceId
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE sources
SET totalImports = (
SELECT COUNT(*)
FROM imports
WHERE sourceId = @sourceId
)
WHERE id = @sourceId
FETCH NEXT FROM deleteCursor INTO @sourceId
END
CLOSE deleteCursor
DEALLOCATE deleteCursor
END
GO
【问题讨论】:
-
到底为什么需要通过触发器更新计数?您始终可以在运行时获得该计数,并且它不依赖于触发器(使用游标,不少于)。如果在选择时获取计数的成本很高,则考虑使用索引视图。应该删除此触发器(以及 totalImports 列)。
-
一般来说,预先计算的汇总并不是解决报告绩效的可取方式,尤其是考虑到它们的非关系性质。但是,如果您的报告是这样编写的,那么我可以看到它们为什么很慢。但是,解决方案仍然没有使用会使您的
INSERTs 和DELETEs 极其缓慢的触发器。更有可能的解决方案是优化报告及其表格和索引。 -
这是一个示例,还使用了更复杂的聚合,并且它们需要实时数据,因此对我来说,在基础记录更改时计算一次而不是在每个请求上计算一次是有意义的.虽然我很喜欢其他方法,但它确实需要持久化而不是在运行时计算。
标签: sql-server tsql triggers