更新sql server中的大量行

Posted

技术标签:

【中文标题】更新sql server中的大量行【英文标题】:Update Large Number of rows in sql server 【发布时间】:2013-11-08 20:16:15 【问题描述】:

我正在尝试更新大约 90,000 行的表中的列。有没有优化的方法来更新表格?

我添加了必要的索引.. 这样就不会发生表扫描/查找。但仍然需要很长时间才能运行(1 小时)。

我的场景:

DECLARE @ParentID   NVARCHAR(100),
        @Con_ERID   INT

DECLARE @MaxCount   INT, 
        @MinCount   INT, 
        @Id         INT

SELECT @MaxCount = MAX(Id) from [dbo].[ParentIDStaging] where Type='grid'

SET @MinCount = 1

WHILE @MinCount <= @MaxCount 
BEGIN

SELECT @Id = ConID FROM [dbo].[ParentIDStaging] WHERE Id = @MinCount  and Type = 'grid'

IF @Id IS NOT NULL
BEGIN

SELECT  @Con_ERID   =   ErId    FROM Context (NOLOCK) Where ConId = @Id
SELECT  @ParentID   =   Identifier FROM Recording (NOLOCK) where ErId = @Con_ERID

    BEGIN TRAN

        UPDATE  [ParentIDStaging]       WITH (ROWLOCK)
        SET [ParentID]   = @ParentID
        WHERE   ContentType = 'grid'
        AND ConID   = @Id

    COMMIT
END

SET @MinCount = @MinCount + 1
END

【问题讨论】:

这是因为您一次更新一条记录并使用显式锁定/事务。 正如其他人所说(我将重复)循环、单独的事务等都会减慢您的速度。我也很好奇 ParentIDStaging.ParentID 是否涉及clustered index 的键中的任何位置。如果是这样,则每次更新都会(几乎可以肯定)导致 ParentIDStaging 中的级联更新,因为表中的行(即使一次只有一个叶节点)被重新排列。如果是这种情况,您最好在循环之前/之后删除并重新创建 clustered index 再次 - 我不知道你的数据/模式/流程 - 但我也很好奇 ParentIDStaging.ParentID 是否总是错误的(并且需要更新)。我以前见过这样的循环,他们更新表中的所有记录,当时只有少数新行具有“错误”值 - 并且简单地将 and ParentID&lt;&gt;@ParentID 添加到 where 对性能产生了深远的影响. 嗨.. ParentID 最初包含 NULL 值.. 我用其他表中的值更新 parentid 列.. 这个 parentid 列需要填充实际值(在 qry 中的更新 stmt ) 而且 ParentIDStaging 表上没有聚集索引..我只在表上创建了非聚集索引,所以不会发生表扫描......但性能仍然很差.. 您是否检查过每个select 是否被覆盖?为什么要将更新分解为单独的事务?所有这些都会产生影响。我会检查索引(因此每个查询/连接都被覆盖),然后查看基于集合的更新 - 而不是循环。 【参考方案1】:

循环很慢。尝试在一次更新中使用连接包含相关的其他表。您的查询可能会这样写(不知道您的实际架构):

UPDATE PS
SET PS.ParentID = Recording.Identifier
FROM ParetnIDStaging PS
JOIN Context on (Context.ConId = PS.ConId)
JOIN Recording on (Recording.ErId = Context.ErId)
WHERE ...

【讨论】:

【参考方案2】:

这是因为您一次循环和更新一条记录并使用显式锁/事务。

在不知道你的底层结构的情况下 - 我敢打赌你可以通过选择更新来做你正在尝试的事情。

【讨论】:

【参考方案3】:
UPDATE ParentIDStaging    
SET parentIdStaging.ParentID=recording.Identifier
from ParentIDStaging   
join Context on context.ConId = ParentIDStaging.ConId
join recording on contect.erid=recording.erId
WHERE   parentIdStaging.ContentType = 'grid'
AND parentidStaging.Type='grid'

【讨论】:

以上是关于更新sql server中的大量行的主要内容,如果未能解决你的问题,请参考以下文章

SQL,更新特定行中的列,而不是所有行

SQL Server 聚合查询中的示例 ID [关闭]

如何在sql server中获取更新的列名

如何在 SQL Server 2008 R2 中的所有行中删除只有一个值的多列

根据行中的值,使用值更新SQL行的最快方法是什么?

SQL Server 锁定的 UPDATE 优化