在加载下刷新汇总表的最佳方法是什么?

时间:2009-01-31 03:12:30

标签: sql-server sql-server-2005 performance transactions deadlock

我在SQL Server 2005数据库中创建了一个表,并使用汇总和计算值填充它。目的是避免每次调用数据库时进行大量连接和分组。我希望这个表每小时更新一次,但我不确定在网站负载时最好的方法。如果我删除每条记录并在一个事务中重新填充表格,那么会不会出现死锁和其他麻烦?

4 个答案:

答案 0 :(得分:5)

我在一些项目中完成此操作的方法是在不同的模式中使用该表的两个副本。如下所示:

CREATE SCHEMA fake WITH AUTHORIZATION dbo;
CREATE SCHEMA standby WITH AUTHORIZATION dbo;
GO

CREATE TABLE dbo.mySummary(<...columns...>);

CREATE TABLE fake.mySummary(<...columns...>);
GO

现在创建一个存储过程来截断并重新填充假表,然后在事务中移动模式之间的对象。

CREATE PROCEDURE dbo.SwapInSummary
AS
BEGIN
    SET NOCOUNT ON;

    TRUNCATE TABLE fake.mySummary;

    INSERT fake.mySummary(<...columns...>)
        SELECT <expensive query>;

    BEGIN TRANSACTION;
        ALTER SCHEMA standby TRANSFER dbo.mySummary;
        ALTER SCHEMA dbo     TRANSFER fake.mySummary;
        ALTER SCHEMA fake    TRANSFER standby.mySummary;
    COMMIT TRANSACTION;
END
GO

这可能是您可以让用户等待刷新新数据并在读取过程中不中断它们的最短时间。 (与NOLOCK相关的许多问题使其成为不太理想的替代方案,但不可否认,它很容易编码。)为了简洁/清晰,我遗漏了错误处理等,我还应该指出,如果你使用用于同步数据库的脚本,确保在两个表上都命名约束,索引等,否则您将在一半的时间内不同步。在程序结束时,你可以TRUNCATE新的fake.MySummary表,但如果你有空格,我想把数据保留在那里,所以我总是可以比较以前的版本。

在SQL Server 2005之前,我在事务中使用了sp_rename来完成同样的事情,但是因为我在一个工作中这样做,所以我很高兴切换到模式,因为当我这样做时,不可抑制的警告来自sp_rename停止填写我的SQL Server代理历史记录日志。

答案 1 :(得分:1)

您还可以创建一个索引视图,具体取决于您的负载有多重,这可能是一个不错的选择

答案 2 :(得分:0)

这取决于数据库中的关系以及针对它运行的查询。

如果它是一个可以容忍陈旧数据的汇总表,您可以使用查询来填充它,使用NOLOCK连接提示执行其SELECT而不使用锁。 注意:只有在确定后果时才能使用NOLOCK提示。

通常可以重新调整索引,以减少负载。

答案 3 :(得分:0)

我决定在@temp表变量中建立数据。然后我将汇总ID复制到它们匹配的临时表中。最后,我将基于@temp表添加,更新和删除汇总表中的行。