SQL Server如何减少存储过程授予的内存量

SQL Server如何减少存储过程授予的内存量,sql,sql-server,Sql,Sql Server,我正在使用SQLServer2008R2 运行sys.dm_os_waiting_任务会显示以下内容: CXPACKET上有很多进程被卡住了。谷歌搜索这个问题表明,这与查询的并行执行有关,我不得不处理MAXDOP设置,但所有进程的资源描述都没有什么意义: exchangeEvent id=Pipe271035100 WaitType=e_waitPipeGetRow nodeId=5 显示e_waitPipeGetRow的Waittype似乎表明它与死锁或大量查询被锁定有关,但我可能错了 我

我正在使用SQLServer2008R2

运行sys.dm_os_waiting_任务会显示以下内容:

CXPACKET上有很多进程被卡住了。谷歌搜索这个问题表明,这与查询的并行执行有关,我不得不处理MAXDOP设置,但所有进程的资源描述都没有什么意义:

exchangeEvent id=Pipe271035100 WaitType=e_waitPipeGetRow nodeId=5
显示e_waitPipeGetRow的Waittype似乎表明它与死锁或大量查询被锁定有关,但我可能错了

我的问题是,如何解决这个问题?我甚至不知道去哪里找

编辑:

自从这个问题发布后,下面的问题突然消失了一段时间。但今天,同样的问题发生了,下面是我在sys.dm_exec_请求中发现的:

有几个PROCID显示了很多数据包。下面是其中一个示例: 123 0 2015-02-10 16:12:21.617挂起选择0x0300070048642C323B8DB30036A400000100000000000000 130411288 0x0500070048642C3240210C1403000000000000000000000000 7 5 59676462-0CB3-4FB8-96FC-530B3892578D 0资源信号量248137资源信号量011583321 0x 0 248138 0x000000000460A748 0 0 -1 한국어 ymd 7 1 0 1 0 1 1 1 2-1 0 0 0 4 0 1 0x941A9D1F032CAA8A 0x1CCA978D548EB09E

显示RESOURCE_信号量的Wait type似乎表明线程在并行运行查询时正在争夺资源,但我不确定。如何对此进行故障排除

编辑2:

啊,现在我终于开始理解核心问题了

运行sys.dm_exec_query_memory_grants向我显示了非常令人惊讶的信息:

有几个进程被授予了大量内存(上图中为3 Gig)。在坏的情况下,一些进程开始请求该内存量,导致资源争用。这就是导致所有资源_信号量等待类型的原因

深入研究,我发现当一个特定的存储过程被反复调用时,就会发生这种情况。我们最终将修复其中的底层SQL问题。我相信这与参数嗅探有关,但为了立即缓解资源争用问题,我尝试采取以下措施:

首先,我运行DBCC FREEPROCCACHE来清除计划缓存。这并没有减少请求的内存量

然后,我尝试使用选项“重新编译”来更改过程。这也没用


所以我真的不知道该怎么办。如何使SP请求更少的内存?

当查询执行并行计划并且某些线程比其他线程先完成时,会遇到这种等待类型。等待其他线程完成的线程显示此等待类型。至于等待描述,我的理解是,这是一种描述线程正在等待其结果被消耗的事实的方法。所以,简而言之,这里没有什么可担心的


但有一点需要注意:为什么线程的工作负载如此不均匀?查看执行计划中每个操作员正在使用多少行的简单方法是使用SQLSentry中的PlanExplorer工具。我猜你会看到一个歪斜。根据我的经验,这通常是由不准确的统计数据造成的。

在第一步,请执行以下操作并重复测试

sp_configure 'show advanced options' ,1
reconfigure
go

sp_configure 'max degree of parallelism',1
reconfigure
go

sp_configure 'show advanced options' ,0
reconfigure
go

完成此配置后,继续测试,看看问题是否得到解决。

SQL server只需要很少的理由来请求这么大的内存,假设它不是一个bug(因为它以前工作正常),那么它一定是一个非最佳查询计划。快速修复方法是更新统计数据和重建索引

如果这没用,恐怕你至少需要做一点调试。知道哪个查询导致了你的大脑老化非常有帮助。在查询中添加
选项(重新编译、强制订单)
提示在很多情况下都会有所帮助

下面的语句也可以帮助您拨打有问题的查询。它列出了计划缓存中的所有查询以及执行次数和平均执行时间。注意,这是一个沉重的语句,禁用获取查询计划将弥补这一缺陷

SELECT [qh] .*, [qp] .query_plan
FROM (SELECT [cp]. [objtype]
          , [Query Hash] = [qs2].[query_hash]
          , [Query Plan Hash] = [qs2].[query_plan_hash]
          , [Total MB] = SUM ( [cp].[size_in_bytes] ) /
               1024.00 / 1024.00
          , [Avg CPU Time]
               = SUM ([qs2] .[total_worker_time]) /
                    SUM ( [qs2].[execution_count] )   
          , [Execution Total]
               = SUM ([qs2] .[execution_count])
          , [Total Cost]
               = SUM ([qs2] .[total_worker_time])
          , [Example Statement Text]
               = MIN ([qs2] .[statement_text])
          , [plan_handle] = MIN ( [qs2].[plan_handle] )
          , [statement_start_offset] =
               MIN ( [qs2].[statement_start_offset] )
     FROM (SELECT [qs].*,
               SUBSTRING ( [st].[text] ,
                    ([qs]. [statement_start_offset] / 2) + 1,
               ((CASE [statement_end_offset] WHEN -1 THEN
                    DATALENGTH ( [st].[text] )
                    ELSE [qs] .[statement_end_offset] END -
                         [qs].[statement_start_offset] ) / 2) + 1)
                         AS [statement_text]
               FROM [sys] .[dm_exec_query_stats] AS [qs]
                    CROSS APPLY [sys]. [dm_exec_sql_text]
                         ([qs]. [sql_handle]) AS [st]) AS [qs2]
               INNER JOIN [sys]. [dm_exec_cached_plans] AS [cp]
                    ON [qs2] .[plan_handle] = [cp] .[plan_handle]
               GROUP BY [cp]. [objtype], [qs2].[query_hash] ,
                    [qs2].[query_plan_hash] ) AS [qh]
CROSS APPLY [sys]. [dm_exec_query_plan]
                         ([qh]. [plan_handle]) AS [qp]
-- For the demo, use the ORDER BY [Example Statement Text]
ORDER BY [Example Statement Text]
-- For the real-world, use the following order by:
-- ORDER BY [qh].[Total Cost] DESC
;
GO

您可以尝试SQL Server附带的资源调控器来限制或保留SQL任务的资源

如果您运行的是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中,您需要打开运算符属性以查看所有内存授予信息

执行计划中的根节点将具有有关查询的内存授予的信息

分配了工作内存的运算符将具有memory Fraction属性,该属性指定该运算符可使用的查询总内存授权的分数

您正在寻找内存分数接近1的运算符,哈希匹配和排序运算符是开始查找的好地方

如果你能