我在sql Server 2005数据库中创建了一个表,并使用汇总和计算值填充它.目的是避免每次调用数据库时进行大量连接和分组.我希望这个表每小时更新一次,但我不确定在网站负载时最好的方法.如果我删除每条记录并在一个事务中重新填充表格,那么会不会发生死锁和其他麻烦?
解决方法
我在一些项目中完成此操作的方法是在不同的模式中使用该表的两个副本.所以类似于:
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代理历史记录日志.