我使用的是 SQL Server 2008 R2
运行 sys.dm_os_waiting_tasks 会显示以下内容:
CXPACKET 上有很多进程卡住。谷歌搜索这个问题表明这与查询的并行执行有关,我必须搞乱 MAXDOP 设置,但所有进程的资源描述没有什么意义:
exchangeEvent id=Pipe271035100 WaitType=e_waitPipeGetRow nodeId=5
显示 e_waitPipeGetRow 的等待类型似乎表明它与死锁或大量查询被锁定有关,但我可能是错的。
我的问题是,如何解决此问题?我什至不知道该去哪里寻找。
编辑:
自从发布这个问题后,下面的问题突然消失了一段时间。但今天,发生了同样的问题,这是我在 sys.dm_exec_requests 中发现的问题:
有几个 PROCID 显示大量 cxpacket。这是其中之一的示例: 123 0 2015-02-10 16:12:21.617 暂停选择 0x0300070048642C323B8DB30036A400000100000000000000 1304 11288 0x0500070048642C3240210C140 30000000000000000000000 7 5 59676462-0CB3-4FB8-96FC-530B3892578D 0 RESOURCE_SEMAPHORE 248137 RESOURCE_SEMAPHORE 0 1 1583321 0x 0 0 0 248138 8 0x00 0000000460A748 0 0 0 -1 한국어 ymd 7 1 0 1 0 1 1 1 1 2 -1 0 0 0 4 0 0 1 0x941A9D1F032CAA8A 0x1CCA978D548EB09E
显示 RESOURCE_SEMAPHORE 的等待类型似乎表明线程在并行运行查询时正在争夺资源,但我不确定。我该如何解决这个问题?
编辑2:
啊现在我终于开始理解核心问题了
运行 sys.dm_exec_query_memory_grants 向我展示了非常令人惊讶的信息:
多个进程被授予大量内存(上图中为 3 Gig)。在糟糕的情况下,多个进程开始请求该内存量,从而导致资源争用。这就是导致所有 RESOURCE_SEMAPHORE 等待类型的原因。
深入研究后,我发现当重复调用特定存储过程时会发生这种情况。我们最终会修复其中底层的SQL问题。我认为这与参数嗅探有关,但为了立即缓解资源争用问题,我尝试采取以下措施:
首先,我运行 DBCC FREEPROCCACHE 来清除计划缓存。这并没有减少请求的内存量。
然后我尝试使用 OPTION RECOMPILE 更改过程。这也没有做任何事情。
所以我非常不知道该去哪里解决这个问题。如何向 SP 请求更少的内存?
最佳答案
如果您运行的是 SQL Server 企业版,您可以使用以下方法将分配给单个查询的最大内存设置为可用服务器内存的百分比:
ALTER WORKLOAD GROUP [DEFAULT] WITH (REQUEST_MAX_MEMORY_GRANT_PERCENT = 25)
GO
-- RECONFIGURE to make the setting take effect
ALTER RESOURCE GOVERNOR RECONFIGURE;
GO
25% 是默认值,减少该值可能会导致与它解决的问题一样多的问题。如果您可以隔离执行问题查询的连接,则可以为这些连接配置单独的限制,请参阅:
资源调控器是企业专用功能,但我了解所有版本都使用默认工作负载组进行标准资源分配。如果有人知道重新配置默认工作负载组是否适用于非企业实例,我会很感兴趣?
要查找问题原因的帮助:
如果您已将问题范围缩小到有问题的存储过程,则执行计划可以告诉您哪些运算符导致了大量内存授予。在SSMS中,您需要打开运算符(operator)属性来查看所有内存授予信息。
执行计划中的根节点将包含有关查询的内存授予的信息。
分配工作内存的运算符将具有“内存分数”属性,该属性指定该运算符异常(exception)使用的查询总内存授予的分数。
您正在寻找内存分数接近 1 的运算符,哈希匹配和排序运算符是开始寻找的好地方。
如果您可以通过更改查询或索引来找到问题区域以消除该操作或减少所涉及的估计行数,则应减少请求的内存授予。
关于SQL Server 如何减少存储过程授予的内存量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28402317/