Troubleshooting SQL Server RESOURCE_SEMAPHORE Waittype Memor

作者:分分快三全天计划网站

 

从上面的SQL查询,我们可以看到大量的事务正处于Resource Semaphore(资源信号量)等待状态。现在我们可以运行下面的SQL语句来查看已分配到内存的查询的目前状态,和未被分配内存的查询的数量。                

SELECT mg.granted_memory_kb, mg.session_id, t.text, qp.query_plan 

FROM sys.dm_exec_query_memory_grants AS mg

CROSS APPLY sys.dm_exec_sql_text(mg.sql_handle) AS t

CROSS APPLY sys.dm_exec_query_plan(mg.plan_handle) AS qp

ORDER BY 1 DESC OPTION (MAXDOP 1)

 

 

当资源信号量(Resource_semaphore)接收到新的请求时,它首先检查是否有任何查询正在等待中。只要发现存在即是一个等待查询,那么会将新查询(新请求)放入队列中,因为等待队列是以先到先得的方式设计的,并且有小权重以支持于小型查询。当没有等待查询或查询返回保留的内存时。资源信号量尝试授予内存。如果找到足够的内存,那么请求内存被授予并且查询可以开始运行,并且如果没有找到足够的可用内存来授予所请求的内存,那么它将当前查询放入等待队列中,并且给当前会话RESOURCE_SEMAPHORE等待类型, 此时服务器开始面临内存压力。

     This wait occurs when queries cannot be compiled due to the amount of compile memory currently available. This mostly occurs due to large queries requiring an excessive amount of memory. SQL Server caps the amount of complex queries that can be compiled at once, so increasing the memory allocation will not solve the problem effectively (it will only increase the amount of memory that can be allocated, not the number of queries)

解决方案

 

ORDER BY lastwaittype

 

  • 使用此提示来识别由于内存不足而消耗更多内存并将剩余的事务置于等待状态的查询。
  • 还要查看上述DMV的其他列,并将它们联系起来,以便更好地分析和了解性能问题。
  • 这些DMV应提供大量信息,以便您能够识别问题。
  • 阅读有关性能调优的更多提示,以提高系统性能。

生成编译计划是件开销较大的事情,因为它需要在数以百计的编译计划中找出较优的一个。它的时间通常很短,因为优化器会在找到最优的编译计划后便马上释放内存。编译主要使用内存和CPU资源。缺少可用内存可能会导致编译延迟和得到非最优的编译计划。    

从sys.dm_exec_query_memory_grants中选择前10个*

 

 

  1. 生成编译计划(compiled plan)。它包括各种逻辑指令,如怎么联接数据行。

下一步

       Occurs when the number of concurrent query compilations reaches a throttling limit. High waits and wait times may indicate excessive compilations, recompiles, or uncachable plans.

 

  1. Improve plan reuse (therefore compilation can be avoided)  改善执行计划重用(因此可以避免编译)

问题描述

 

 

 

** 

另外,内存紧张也会导致RESOURCE_SEMAPHORE_QUERY_COMPILE的出现的概率增加,那么是否增加内存就有效解决RESOURCE_SEMAPHORE_QUERY_COMPILE等待事件呢?答案是否定的,但是能缓解。如下描述:

 

  额外内存:存储所有临时数据行所需的内存。它的大小由基数评估(Cardinality estimate,如行数和行大小)决定。“额外”,顾名思义在缺少这部分内存时,将会将临时数据行存到硬盘上,并不会导致查询失败。一个查询的额外内存大小如果超过预设的限制,它实际得到的内存量并不一定会跟请求量一样。

SELECT * FROM sys.dm_exec_sql_plan(plan_handle)   --译者注  实际没有sys.dm_exec_sql_plan, 而是sys.dm_exec_query_plan,估计是作者笔误。

 

 

  必须内存:执行排序和哈希联接所需的最少内存。这部分内存是“必须”的,它用来创建处理排序和哈希所需要的内部数据结构。

 

当SQL Server创建编译计划时,会计算两个参数:必须内存(Requeried memory)和额外内存(Additional memory)。

 

 

 

个人曾遇到过这样一个案例,由于过度灵活设计,导致很多报表需要在SQL中大量关联相关表,更糟糕的是,由于开发人员大量使用视图,尤其是还存在视图嵌套视图的情况,所以在这样一个系统中,一些查询语句往往需要授予大量的内存,尤其是当出现一个或一些写的很糟糕的SQL语句时,就会经常看到一些会话处于RESOURCE_SEMAPHORE_QUERY_COMPILE的等待状态,而且当大量会话处于RESOURCE_SEMAPHORE_QUERY_COMPILE等待时,还有一个特殊现象就是活动的会话数量会彪增,此时,可以找到消耗内存最多的SQL,然后Kill掉后,活动的会话就会立即降下来。下面就是我遇到案例的一个截图。

** 

  

** 

 

步骤1

  如果你的数据库经常看到这种等待事件或此等待类型过多,那么你的数据库可能会有太多内存密集型查询(大型查询),或者其他进程可能正在从缓冲池中窃取内存页面.

 

3. 从指令树的顶端开始执行。

步骤4

 

现在,我们将找到内存密集型查询。我们可以看到所有等待查询的请求内存。在这里我们可以看到所请求的内存对于大多数事务来说太大了。我们将获得所有这些查询的plan_handle,以获得确切的SQL文本来查看查询计划。

  当编译计划中含有多个排序和联接操作时,额外内存的计算就变得复杂了。因为SQL Server要考虑所有操作符如何高效地使用内存。可以查看ShowPlan XML中的<MemoryFractions>标记部分内容,获取更多内存使用的信息。

 

关于等待事件RESOURCE_SEMAPHORE_QUERY_COMPILE,官方的介绍如下:

运行以下语句从上述查询中获取SQL代码,使用sql_handle。

 

当SQL Server收到用户发送的查询请求(查询语句)时,它首先创建一个编译过的计划,然后在这个基础上创建一个执行步骤(个人觉得执行步骤比执行计划要合适)。当SQL Server创建一个编译过的计划时,它会计算两个内存授予参数,称为“请求内存”(required memory)和“附加内存”(additional memory)。请求内存是运行排序和HASH连接所需的最小内存。它之所以是 "必需"的, 是因为如果没有可用的“请求内存”, 查询将无法启动。附加内存(additional memory)是在内存中存储临时行(个人觉得翻译为中间结果可能更合理)所需的内存量。这被称为额外(附加)的,因为如果没有足够可用的“附加内存”可以将查询的中间结果存储在磁盘上。 

 

首先,我们需要研究我们的实例,弄清楚为什么在SQL Server中出现内存压力。要查看所有事务的大概信息,我们可以查询sys.sysprocesses,或者我们可以使用sys.dm_exec_requests DMV。

  1. kill掉一些糟糕的SQL语句(内存资源密集型SQL),当然这个要看是否可行。

分分快三全天计划网站 1

 

 

 

现在我们将使用上面查询所获得的plan_handle和sql句柄来获取SQL代码。

分分快三全天计划网站 2

今天,我们的一个SQL Server实例性能变得非常慢。当我登录到数据库服务器进行一些初始检查时,我最初始观察、注意到的是它的内存压力(memory pressure)。接下来,我们必须找出是什么导致我们的实例出现内存紧张。当我检查事务的等待类型时,RESOURCE_SEMAPHORE等待是大多数事务的问题。在这篇文章中,我将描述这个问题,以及如何查找哪个查询语句或事务导致了内存压力

在继续之前,我想对资源信号量(Resource_semaphore)等待进行一些说明,以便您可以更好地了解SQL Server是如何将内存授予SQL Server查询语句的。

减少等待事件方案

分分快三全天计划网站 3

内存授予的等待类型叫做“RESOURCE_SEMAPHORE”.在理解这个等待事件前,我们先来了解一下查询内存授予(query memory grant),它是用于在排序或连接时存储临时数据的服务器内存的一部分。查询在实际执行前需要先请求保留内存,所以会存在一个授予的动作。这样的好处是提高查询的可靠性和避免单个查询占用所有的内存。

 

 

 

 

 

 

 

  1. Decrease query complexity 降低查询语句的复杂度。

SELECT * FROM sys.dm_exec_query_memory_grants

 

 

 

 

注意:有太多列要显示,可以只显示部分所需的列。

 

我们还可以使用步骤4中查询中的plan_handle获取SQL计划。

https://blogs.msdn.microsoft.com/sqlqueryprocessing/2010/02/16/understanding-sql-server-memory-grant/

SELECT * FROM sys.dm_exec_sql_text(sql_handle)

  1. Appropriate indexing could reduce plan complexity  合理创建索引减少执行计划复杂度

 

 

步骤2

等待事件分析

现在我们已经找到内存密集型查询及其执行计划,我们的下一步是研究这些查询,并找出如何调整、优化它们。我们应该查看查询中是否使用的错误的索引或是否存在索引缺失的情况,并创建正确的索引。在我们这种情况下,这是由于糟糕的索引设计导致了内存紧张。在创建、调整合适的索引之后,相同的查询运行的时候请求的内存就会少得多。

 

 前言: 本文是对博客的翻译,本文基本直译,部分地方读起来有点不自然。 如有翻译不对或不好的地方,敬请指出,大家一起学习进步。尊重原创和翻译劳动成果,转载时请注明出处。谢谢!

 

2. 生成执行计划(execution plan),它包含将编译计划中的各种逻辑引用转换成实际的对象的指令和查询执行的跟踪机制。

SELECT * FROM sys.dm_exec_query_resource_semaphores

SQL Server在收到查询时,会执行3个被定义好的步骤来返回用户所请求的结果集。

分分快三全天计划网站 4

 

** 

 

现在我们将获取所有正在等待队列中获取所请求的内存的所有查询的详细信息,我们将使用DMV sys.dm_exec_query_memory_grants来获取队列中等待分配内存的查询总数。对于等待获取其请求的内存的查询,grant_timegranted_memory_kb列将为NULL。您可以在下面的截图中查看所请求的内存量及其等待状态,因为它们的grant_time和granted_memory_kb值为NULL。我们还可以使用该DMV获取所有查询的plan_handle和sql_handle。稍后我们将使用这些值来获取确切的查询。

  

select top 10 * from sys.dm_exec_query_memory_grants

例如,对行大小为10byte的100万行数据进行排序,此查询的必须内存为为512KB(此值是SQL Server处理一个排序操作创建内部数据结构所需的最小内存量)。为了存储所有数据行,额外内存可能是10MB。

步骤5

等待事件介绍

 

 

当我检查所有事务的等待类型时,大多数事务的等待类型为RESOURCE_SEMAPHORE 等待以及某些页面IO等待。页面IO等待也是由于内存压力导致,因为这些事务无法获得足够的内存来执行这个操作。

 

结论

 

** 

 

** 

参考资料:

 

RESOURCE_SEMAPHORE_QUERY_COMPILE等待事件一般是查询正在等待授予内存以开始进行编译时发生。编译内存来自缓冲池(buffer pool),并需要保留足够的时间以完成编译过程。 对于多个并发编译而言,占用太多内存页可能会导致内存压力。 为了缓解这种情况,SQL Server启动编译过程,确定哪些查询需要大量的页面,并迫使某一些查询会话等待。 同样,如果内存压力已经存在,SQL Server将限制可以同时编译的资源密集型查询的数量。

识别RESOURCE_SEMAPHORE等待

 

该等待事件在并发查询编译的数量达到阀值限制时出现。 等待时间较长或等待次数较多可能表明编译、重新编译或不能缓存的计划过多。

该DMV的输出返回两行,一个表示大型查询(resource_semaphore_id为0),另一个表示小型查询(resource_semaphore_id为1),小于5 MB。在这里,您可以获得实例的总授予内存和总可用内存。请参阅grantee_countwaiter_count上的数字,grantee_count是已经分配了内存的总查询数,waiter_count是队列中等待获取内存的总查询数量。所以在这里我们可以看到大约100个查询正在等待获得他们要求的内存。

 

 

 

首先,服务器计算任何给定的查询执行需要多少内存。这通常是“请求内存”(required memory)和“附加内存”(additional memory)的总和,但如果您的实例正在并行处理,那么所需的内存将是(所需的内存* DOP) 附加内存。服务器检查所需的内存是否超过每个查询限制,然后服务器减少“附加内存”,直到总数达到限制。这个修改后的大小称为请求内存。SQL Server有一个内部工具称为资源信号量(RESOURCE SEMAPHORE),用于将此请求的内存授予查询。如果无法通过资源信号量向该请求的内存授予查询,那么如果查询sys.sysprocesses系统表或​​sys.dm_exec_request DMV,则该查询将处于等待状态,并出现RESOURCE_SEMAPHORE等待类型。

 

 

** 

 

分分快三全天计划网站 5

这里我们可以看到所有产生RESOURCE_SEMAPHORE等待类型的进程。

步骤3

资源信号量等待

分分快三全天计划网站 6

                                                       

SELECT * FROM sys.sysprocesses

** 

本文由分分快三计划发布,转载请注明来源

关键词: 分分快三计划