Sql server 将列设置为NULL时更新速度慢

Sql server 将列设置为NULL时更新速度慢,sql-server,sql-server-2008,Sql Server,Sql Server 2008,我有一个包含80000行的SQL Server 2008表,正在执行以下查询: UPDATE dbo.TableName WITH (ROWLOCK) SET HelloWorldID = NULL WHERE HelloWorldID = @helloWorldID HelloWorldID是一个int,@HelloWorldID参数也是int 查询时间太长,我想对其进行优化。我在HelloWorldID上创建了一个非聚集索引,但这并不重要。我可能需要重新设计这个…可能将HelloWorld

我有一个包含80000行的SQL Server 2008表,正在执行以下查询:

UPDATE dbo.TableName WITH (ROWLOCK)
SET HelloWorldID = NULL
WHERE HelloWorldID = @helloWorldID
HelloWorldID
是一个
int
@HelloWorldID
参数也是
int


查询时间太长,我想对其进行优化。我在
HelloWorldID
上创建了一个非聚集索引,但这并不重要。我可能需要重新设计这个…可能将
HelloWorldID
放在另一个表上,该表将它链接到
TableName
表?

这一切都取决于此查询将更新多少行。 如果您要更新很多行,比如表的30%,那么索引实际上会减慢查询速度(因为索引将随表一起更新,并且它无助于筛选要更新的行)。另外,ROWLOCK将使其速度减慢,因为引擎将为每一行发出一个单独的锁(与通常发生的页面锁相反)。
尝试删除索引并使用
WITH(TABLOCK)
运行此更新,看看会发生什么。

因为您等待的命令是
DELETE
,我不得不猜测在
dbo.TableName
上有一个触发器,它正在执行您不期望的额外工作。或者可能是某个影响其他具有触发器的表的
级联
选项。

我有时会遇到这个问题。您的查询依赖于在满足WHERE子句条件的表中的每一行上同时获得写锁。根据您对全“酸”的需求,您可以这样做:

SELECT getdate()  -- force @@rowcount=1
while @@rowcount > 0
UPDATE TOP (1000) dbo.TableName 
SET HelloWorldID = NULL
WHERE HelloWorldID = @helloWorldID

这将做更新是更小的块,并有助于克服锁定问题。但请记住,此方法放弃将此查询作为单个事务进行。您需要将1000调整为适合您的服务器的值

你能把执行计划贴在什么地方吗?参数的数据类型是什么,列的数据类型是什么,您希望匹配多少行?当它运行时,您在
sys.dm_exec_请求中看到了哪些等待类型和SPID阻塞?这两种类型的数据类型都是“int”。我希望能和一排比赛。我可以在哪里发布执行计划?以什么格式发布?我看到PAGEIOLATCH_EX表示等待类型和无阻塞,但命令是DELETE。如果命令是DELETE,则可能(a)这是更大查询/事务的一部分,或者(b)有一个您不知道或尚未调查的触发器。执行计划采用.sqlplan格式。如果您有空闲时间,可以在工具中发布.queryanalysis文件。否则,只需选择您最喜欢的文件共享服务,只要它不需要我们创建帐户或登录即可。免责声明:我为SQL Sentry工作。谢谢Aaron!我在你的网站上发布了这个问题的链接。谢谢你的回答…似乎没有什么区别,因为我只希望有一行。我在那个数据库上没有任何触发器。@richinator38好吧,SQL Server不会神奇地将你的
更新
本身变成
删除
,所以一定有一些事情你还没有发现(或者没有透露)。为什么要使用
ROWLOCK
?这是一笔更大的交易的一部分吗?看起来这里还有别的事情。我发布的代码处于一个存储过程中,如果我一次只执行一个调用,它将快速运行。但是,存储过程是从循环通过多个ID的SSIS作业调用的。如果我查看探查器的输出,“Audit Logout”事件花费的时间似乎最多。我建议为此使用表值参数,而不是SSI为一组值反复调用过程。SSI从何处获取要调用该过程的ID列表?另一个过程获取ID列表。我使用ID 1)从源数据库中删除文档,然后2)更新行以清空文档的ID。我正在SSIS中使用事务选项,这似乎有点帮助。在进行所有更改之前,更新将一次更新1000行。第一行“select getdate()'强制@@rowcount=1。然后更新语句将@@rowcount=1000放在后面,直到要更新的数目少于1000。然后@@rowcount等于更新的数目。我一直都在执行这种while循环。是的,我理解您的代码试图执行的操作。我告诉你OP的where子句只标识一行,所以速度问题与批处理完全无关。您的循环将只运行一次,并且仍然只更新一行。OP从未说过where子句中的字段是主键。他在该字段上创建了一个非聚集索引,并且存在pagelatch问题,我认为它不是主键。我的解决方案只有在它不是主键时才有帮助,该字段不仅在表中不唯一,而且编辑的值在许多行上。