我有一个疑问:
select * from Aview where field=20
order by id desc
Run Code Online (Sandbox Code Playgroud)
这将在大约 1 秒内从视图中返回 2700 行。
在查询中添加“top 20”使 MSSQL 在 43 秒内返回!
这是一个很难重现的问题,重建统计数据可以修复该问题几天,但随后又回来了。
我使用 SQL 已经有几十年了,我从未见过添加“top”导致时间增加的情况。
查看执行计划,如果执行前 20 条,它似乎正在执行 9.6 亿行的惰性假脱机操作,但如果不执行,则不会执行。
我很确定我明白这一点,但我想确定我明白。我们有一个 SQL Server 2016,它运行着 2 个 NumaNode,每个 NumaNode 有 8 个 vCPU。最大并行度 (MAXDOP) 设置为 8。
这对我来说听起来不对。第一个问题:这是一个像我认为的那样糟糕的想法吗?
根据我的研究,我需要告诉他们减少 VM 设置以使其在单个 NUMANode 中运行。我们似乎遇到了一些随机时期,其中运行时间为 170 毫秒的查询现在超时时间为 30 秒以上!因此,我们快速查看了一下,CPU 使用率为 5%,磁盘 I/O 使用率较低,网络使用率合理......基本上,机器处于空闲状态。我们还查找了等待锁的查询,并且没有。我们正在 AG 组中的辅助节点上运行查询(只读查询)
所以,我的猜测是:它已经获得了足够的负载,可以在第二个 NUMANode 中的一个 vCPU 上切换并运行一个有问题的视图(每天运行大约 4,000 次),然后决定执行计划应该始终运行在那个节点。结果是它正在访问的所有数据都缓存在另一个节点的内存中,并且它需要通过节点间链接(远程内存)来获取它,所以它这样做了,但最终速度慢了很多(170次?),并且查询现在都在这个远程链接上运行越来越多的查询......直到它总是超时,因为远程内存已饱和......
这样的分析有效吗?我不想将其作为解决方案来提交,以解释为什么如果这完全不正确,查询会突然及时跳转。而且很难让他们相信 8 个 CPU 会比 16 个 CPU 获得更好的性能。
哦,还有更多证据来支持我的说法:如果我select * into #tmp from myView OPTION (MAXDOP 16)这样做,我的性能变化约为 -5% 到 -12% - 这意味着运行查询所需的时间比我只使用 8 个 vCPU 时要长。然而,情况并非如此。
所以我的问题是:我的分析是否有效?
更新:还有其他一些事情,我从以下位置获得了很多信息:https://codenotary-compliance.medium.com/vmware-vsphere-why-checking-numa-configuration-is-so-important-9764c16a7e73
其次,如果我执行select * from sys.[dm_os_nodes] then 我得到foreign_commited_KB为5,414,260或5 GB,从上面的信息来看,这听起来像是从另一个节点提交的(这很糟糕?)