【问题标题】:Gather Streams operator before table update causing serial update leading to long running query in SQL Server 2017在表更新导致串行更新导致 SQL Server 2017 中长时间运行的查询之前收集流运算符
【发布时间】:2021-04-24 10:08:56
【问题描述】:

我有一个长时间运行的存储过程,其中包含很多语句。经过分析确定了花费最多时间的几个语句。这些语句都是更新语句。

查看执行计划,查询在几秒钟内并行扫描源表,然后将其传递给收集流操作,然后传递给

这有点类似于下面,我们看到索引创建语句的相同行为也会导致缓慢。

https://brentozar.com/archive/2019/01/why-do-some-indexes-create-faster-than-others/

表有 6000 万条记录,在我们进行大量数据加载、更新和删除时是一个堆。

读取源代码不是问题,因为它在几秒钟内完成,但连续发生的实际更新需要大部分时间。

【问题讨论】:

  • 您要插入的表的架构是什么,它有聚集索引还是非聚集索引?
  • 啊。我认为这是一个错字,但无法解决。

标签: sql-server query-optimization sql-server-2017 sql-server-performance


【解决方案1】:

一些尝试的建议:

如果您在目标表上有索引,则在之前删除它们并在之后重新创建应该会提高插入性能。

insert into [Table] with (tablock) 提示添加到您要插入的表中,这将使 sql server 能够以独占方式锁定表并允许插入也并行运行。

或者,如果这没有产生改进,请尝试在查询中添加 maxdop 1 提示。

【讨论】:

  • 问题不在于插入。我们已经在使用 tabblock。缓慢是当我们执行更新时它在更新堆时变为串行。该表没有聚集索引,但有 2 个非聚集索引来支持存储过程中的许多其他查询,因此我们不能删除那些非聚集索引。
  • 更新已经切换到串行,同时更新大部分时间占用的堆。希望此堆更新并行发生。请看我的问题中引用的文章
【解决方案2】:

您多久更新一次此堆中的行? 因为,与聚集索引不同,堆将使用 RID 来查找特定行。但问题是(除非您专门重建它)当您更新一行时,最后一行仍将保留在原来的位置,现在指向新位置,从而增加每次执行时所需的查找次数连续更新。 我真的不认为这会在这里受到影响,但是如果您在表上添加聚集索引并查看更新时间如何受到影响,您能否看到会发生什么?

另外,我不认为你在桌面上有一些重要的触发器,也做了很多事情,对吧?

此外,由于您指的是 Brent Ozar 的一篇文章,他确实主张将更新分成每次不超过 4000 行的批次,因为这已被证明是最快的并且将低于 5000 行更新期间将发生的 X 锁定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 2013-03-29
    • 1970-01-01
    • 2015-11-25
    • 1970-01-01
    相关资源
    最近更新 更多