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

时间:2015-02-09 03:22:35

标签: sql sql-server

我正在使用SQL Server 2008 R2

运行sys.dm_os_waiting_tasks会显示以下信息:

enter image description here

很多进程都停留在CXPACKET上。谷歌搜索这个问题表明,这与查询的并行执行有关,我必须搞乱MAXDOP设置,但所有进程的资源描述都没有意义:

exchangeEvent id=Pipe271035100 WaitType=e_waitPipeGetRow nodeId=5

显示e_waitPipeGetRow的Waittype似乎表明它与死锁或大量查询被锁定有关,但我可能错了。

我的问题是,如何解决此问题?我甚至不确定在哪里看。

编辑:

自发布此问题以来,下面的问题突然间暂时消失了。今天,同样的问题发生了,这是我在sys.dm_exec_requests中找到的:

enter image description here

有几个PROCID显示了很多cxpacket。以下是其中一个示例: 123 0 2015-02-10 16:12:21.617暂停SELECT 0x0300070048642C323B8DB30036A400000100000000000000 1304 11288 0x0500070048642C3240210C14030000000000000000000000 7 5 59676462-0CB3-4FB8-96FC-530B3892578D 0 RESOURCE_SEMAPHORE 248137 RESOURCE_SEMAPHORE 0 1 1583321 0x 0 0 0 248138 8 0x000000000460A748 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的等待类型似乎表明线程在并行运行查询时争用资源,但我不确定。我该如何解决这个问题?

EDIT2:

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

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

enter image description here

几个进程被授予了大量内存(上图中为3个Gigs)。在不好的情况下,有几个进程开始请求大量内存,导致资源争用。这就是导致所有RESOURCE_SEMAPHORE等待类型的原因。

深入挖掘,我发现在重复调用特定存储过程时会发生这种情况。我们最终将修复其中的基础SQL问题。我认为它与参数嗅探有关,但为了立即缓解资源争用问题,我尝试采取以下措施:

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

然后我尝试用OPTION RECOMPILE改变程序。这也没有做任何事情。

所以我很遗憾去哪儿。如何使SP请求​​更少的内存?

5 个答案:

答案 0 :(得分:4)

如果您运行的是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%是默认值,减少这可能会导致尽可能多的问题。如果您可以隔离执行问题查询的连接,则可以为这些连接配置单独的限制,请参阅:

Sql Server Resource Governor

资源调控器是企业唯一的功能,我知道所有版本都使用默认工作负载组进行标准资源分配。如果有人知道重新配置默认工作负载组是否适用于非企业实例,我会感兴趣吗?

要找到帮助以解决问题的原因:

如果您已将问题缩小到问题存储过程,则执行计划可以告诉您哪些操作符导致大内存授予。在SSMS中,您需要打开运算符属性以查看所有内存授予信息。

执行计划中的根节点将包含有关查询的内存授权的信息。

分配工作内存的运算符将具有“内存分数”属性,该属性指定运算符除外使用的查询总内存授权的分数。

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

如果您可以找到更改查询或索引的问题区域以消除操作或减少所涉及的估计行数,则应减少所请求的内存授予。

答案 1 :(得分:1)

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

但要注意的一件事是:为什么线程会产生如此不均匀的工作量?查看执行计划中每个操作员消耗的行数的简便方法是使用SQL Sentry中的Plan Explorer工具。我的猜测是你会看到一个倾斜。根据我的经验,这通常是由不准确的统计数据引起的。

答案 2 :(得分:0)

SQL服务器提出内存量的原因很少,假设它不是一个错误(因为之前工作正常),它必须是一个非最佳的查询计划。快速修复将更新统计信息和重建索引。

如果这没有帮助,我担心你至少需要做一些调试。知道哪个查询导致您的头龄有助于帮助很多。在查询上添加OPTION(RECOMPILE, FORCE ORDER)提示有助于很多情况。

以下声明还可以帮助您拨入有问题的查询。它列出了计划缓存中的所有查询以及执行次数和平均执行时间。请注意,这是一个沉重的陈述,禁用获取查询计划将修复该问题。

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

答案 3 :(得分:0)

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

答案 4 :(得分:-7)

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

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

完成此配置后,继续进行测试,看看问题是否已解决。