sql-server – 巨大的表上的大型滚动更新:越来越慢

SQL Server 2014标准版

我们有一个有1亿行的表.

我们需要更新几列中的值.

我们做了以下操作,现在已经运行了18个小时,并且只完成了1700万行.它变得越来越慢.

它是一个相当热门的服务器和磁盘系统(EMC RAID10等等). CREATE INDEX花了大约20分钟(我们不得不忍受的不幸中断).

我们可以用什么方法更快地完成这项工作? (在线强烈推荐)

CREATE NONCLUSTERED INDEX RECORD_DELETED_INDEX ON [dbo].[huge-table] ( [deleted] ASC, [deletedDate] ASC );
GO


DECLARE @CHUNK_SIZE int
SET @CHUNK_SIZE = 4000  -- to stay under lock escalation threshhold

UPDATE TOP(@CHUNK_SIZE) [huge-table] set deleted = 0, deletedDate = '2000-01-01'
where deleted is null or deletedDate is null

WHILE @@ROWCOUNT > 0
BEGIN
    UPDATE TOP(@CHUNK_SIZE) [huge-table] set deleted = 0, deletedDate = '2000-01-01'
    where deleted is null or deletedDate is null
END
最佳答案
将索引创建为过滤器(即使用WHERE子句)可能会更好,因为当您更新了更多的记录时,它会变得更小,然后会过滤掉它:

CREATE NONCLUSTERED INDEX RECORD_DELETED_INDEX
  ON [dbo].[huge-table] ( [deleted] ASC, [deletedDate] ASC )
  WHERE deleted is null
  OR    deletedDate is null;

但是,每次循环运行时,您仍然会遇到扫描该索引的问题.表中有1亿行并且每次迭代更新4000次,这是扫描表(或索引)以查找要更新的行的25,000次.如果减少查询表的次数最好.

请参阅我关于此项目的其他一个问题的答案,其中的设置应使此过程更快:

sql server: updating fields on huge table in small chunks: how to get progress/status?

在那个答案中,我展示了如何只查询大表100次.每次它抓取聚集索引键字段并将它们用于所有UPDATE查询,以便更新快速.并且该设置还允许快速获取操作的当前进度(并且无需查询表!)并且干净地取消该过程.

应该指出的是,这个问题涉及以下问题(按时间顺序列出):

> sql server: updating fields on huge table in small chunks: how to get progress/status?(如上所述)
> Are explicit transactions needed in this while loop?
> SQL Server lock_escalation flag on ALTER TABLE — can I really restructure without a table lock?

转载注明原文:sql-server – 巨大的表上的大型滚动更新:越来越慢 - 代码日志