Joh*_*ner 13 performance sql-server sql-server-2016
我在4个vCPU VM运行Microsoft SQL Server 2016 SP2-CU6(13.0.5292.0)与max degree of parallelism
设置为2
和cost threshold for parallelism
设置为50
。
早上,当我尝试显示SELECT TOP 100查询的估计执行计划时,我遇到了大量等待,并且呈现估计计划的操作需要几分钟,通常在 5 到 7 分钟的范围内。同样,这不是查询的实际执行,这只是显示Estimated Execution Plan 的过程。
sp_WhoIsActive
将显示PAGEIOLATCH_SH
等待或LATCH_EX [ACCESS_METHODS_DATASET_PARENT]
等待,当我在操作期间运行Paul Randal 的 WaitingTasks.sql脚本时,它显示CXPACKET
等待,工作线程显示PAGEIOLATCH_SH
等待:
*资源描述字段= exchangeEvent id=Port5f6069e600 WaitType=e_waitPortOpen waiterType=Coordinator nodeId=1 tid=0 ownerActivity=notYetOpened waiterActivity=waitForAllOwnersToOpen
工作线程看起来将整个stats
表带入内存(因为这些页码以及从 Paul Randal 的查询点显示的后续页码指向stats
表的聚集键)。一旦计划确实回来了,即使在我看到stats
缓存中的大部分表损耗,只剩下各种记录(我认为由于类似查询的搜索操作而被拉出)之后,它在当天剩余时间内基本上是即时的。
如果查询实际上是使用使用 SCAN 运算符的计划执行的,我会期望这种初始行为,但是为什么在评估执行计划时这样做只是为了到达上面链接的计划中所示的 SEEK 运算符?我可以做些什么(除了在办公时间之前运行此语句以便适当缓存我的数据)来帮助提高性能?我假设一对覆盖索引将是有益的,但它们真的能保证行为的任何变化吗?我必须在此处处理一些存储和维护窗口限制,并且查询本身是从供应商解决方案生成的,因此此时欢迎任何其他建议(除了更好的索引)。
Jos*_*ell 13
看来您对实际执行计划的请求触发了统计信息更新。既然你提到这发生在早上,我想有一个通宵流程对所涉及的表格进行了大量修改?
因此,SQL Server 使用统计信息创建计划,达到修改阈值,并执行自动统计更新作为操作的一部分。
在您分享的估计计划的 XML 中,我看到了这些从今天早上开始的统计数据的最新更新日期:
LastUpdate="2019-05-06T09:12:49.92"
LastUpdate="2019-05-06T09:12:58.3"
LastUpdate="2019-05-06T09:13:20.33"
LastUpdate="2019-05-06T09:13:09.67"
LastUpdate="2019-05-06T09:12:59.05"
LastUpdate="2019-05-06T09:12:39.56"
Run Code Online (Sandbox Code Playgroud)
如果这些是非常大的,繁忙的表(很可能基于采样百分比),那么这不是太奇怪的是,统计数据的更新都采取了很大的马力。
当我在 SSMS 中看到很长的估计计划时间时,按可能性顺序是以下之一:
对于您的情况,答案几乎肯定是 SQL Server 正在更新或创建统计信息。有几点线索:查询计划的规模较小,查询计划相对简单成本低,编译CPU明显低于编译时间:
新的贡献者Josh Darnell还指出了一个很好的线索,即 XML 中统计数据的最后更新时间。
SQL Server 2019 引入了一种新的等待类型WAIT_ON_SYNC_STATISTICS_REFRESH,用于当查询等待统计信息更新时。在那个版本上诊断这个问题要容易得多。在此之前,您将只需要依靠间接技术。
解决方法包括在维护期间更新统计信息或为数据库启用自动更新统计信息异步。请在更改之前了解该选项的全部后果。查询计划将在统计信息更新之前而不是在统计信息更新之后创建。对于某些工作负载来说,这可能是一个巨大的胜利。对于其他人来说,它弊大于利。