此文描述查询内存授予(query memory grant)在SQL Server上是如何工作的,适用于SQL 2005 到2008。

查询内存授予(下文缩写为QMG)是用于存储当数据进行排序和连接时的临时中间数据行。查询在实际执行前需要先请求保留内存,所以会存在一个授予的动作。

这样的好处是提高查询的可靠性和避免单个查询占用所有的内存。

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

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

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

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

生成编译计划是件开销较大的事情,因为它需要在数以百计的编译计划中挑出较优的一个。每一个编译计划都能被缓存,并被多个执行计划共享使用。

内存授予预估的有些参数被存储在编译计划当中,并且它本身有一个机制用于计算在实际执行时需要授予给查询的内存大小。

内存使用者(Memory Consumers)

一个成功执行的查询包括三个主要的内存使用者:编译,缓存和内存授予。

编译:创建和在数以百计的计划当找到最优的编译计划是件很耗内存的事。它的时间通常很短,因为优化器会在找到最优的编译计划后便马上释放内存。

编译主要使用内存和CPU资源。缺少可用内存可能会导致编译延迟和得到非最优的编译计划。

缓存: 为了编译计划重用,SQL Server会把编译计划保存到缓存中。它会长时间占用内存。如果缺少可用内存会导致不必要的重编译。

内存授予:这部分主要用于存储当数据进行排序和连接时的临时中间数据行。缺少可用内存会导致查询使用硬盘来暂存数据,降低查询性能。

SQL Server使用内存代理(Memory Broker)来平衡三个使用者对内存的使用。基于使用者需要的内存和可用物理内存,如果内存代理预估到内存不足时,便会设定内存使用限制并通知三者削减各自内存使用量。

授予参数(Grant Parameters)

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

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

额外内存:存储所有临时数据行所需的内存。它的大小由基数评估(Cardinality estimate,如行数和行大小)决定。“额外”,顾名思义在缺少这部分内存时,将会将临时数据行存到硬盘上,并不会导致查询失败。

一个查询的额外内存大小如果超过预设的限制,它实际得到的内存量并不一定会跟请求量一样。

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

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

并行度依赖(DOP Dependence)

当SQL Server使用多个CPU时,可以将查询分解到到多个工作者线程并行执行来提高性能。这些工作者线程相互独立运行,然后使用并行操作符(Parallelism operator a.k.a Exchange)传输数据。

并行模式增加了内存的使用,因为并行的每个工作者都 需要一份排序和联接的数据副本并且并行操作符需要缓存所有被传输的临时数据。因此DOP N会使用N倍所需的内存。

然而,需要处理的数据行数和存储它们的内存量并不会随着DOP的改变而改变。也就是说,额外内存不会因DOP面改变。从SQL 2008开始并行操作符使用的缓存内存也被算成必须内存授予。

内存授予过程(Memory grant process)

SQL Server需要考虑服务器内存量和并发查询数量来避免最终提交的内存量超过物理内存限制.这分两步完成,首先它计算需要分配多少内存给某个查询,然后使用内部因子-资源信号量(Resource Semaphore)去保留实际内存,或者当过多查询请求内存时,它会调节(Throttle)这些请求.按照下面的步骤来确定内存请求量:

1. SQL Server根据服务器状态和计划来确定最大并行度.

2. SQL Server检查是否需要执行内存授予,如果不需要则马上执行查询.例如查询中没有group by 或order by,则不需要进行内存授予.

3. 为单个查询计算内存限制,默认值=0.25(32bit SQL 2000为0.2)*0.9*Server内存.这个比值在SQL 2008是可配置的.单个查询的内存限制,避免了一个查询占用所用服务器内存.

4. 计算理想情况下必须的查询内存量=理想内存需求量*DOP+额外内存(+Exchange on SQL 2008).

5. 然后检查理想内存理是否超过单个查询内存限制.如果超过,则会减少额外内存量,直到符合单个查询内存限制.这个修正后的内存称为被请求的内存(Requested memory),SQL Server调用资源信号去授予这个被请求的内存.

资源信号量(Resource Semaphore)

资源信号量负责调整和满足内存授予请求,以保证它们的使用量在服务器的限制内.

1. 只当有足够空闲内存时,资源信号才允许查询保留内存.否则将会被排进一个等待队列.

2. 当资源信号量收到一个查询请求时,会先检查等待队列中是否有正在等待的请求,如果有,则此请求也会被放进此FIFO的队列中.

3. 当队列中无等待的查询或者之前的查询返回被保留的内存时,资源信号会尝试授予内存。

4. 如果找到等待的查询时,请求的查询将会被入进队列中。

5. 如果没有等待的查询,它会检查可用空闲内存。

6. 如果找到足够的空闲内存,则授予查询所请求的内存。查询就可以开始运行了。

7. 如果没有找到足够的空闲内存,则当前查询会被放进等待队列。

8. 当有足够的可用空闲内存时,资源信号量会唤醒队列中等待的查询。

调试内存授予相关的问题

SQL Server 提供了一些DMV用于分析内存授予相关的问题。

sys.dm_exec_query_resource_semaphores

此视图返回当前资源信号量的状态。它返回两行,一行叫常规资源信号量(max_target_memory_kb列为非NULL),一行叫小型资源信号量(小于5MB的查询)。

sys.dm_exec_query_memory_grants

返回已经获得内存授予和正在等待内存授予的查询相关信息。正在等待的查询的grant_time列会是NULL。资源信号量使用内部查询成本来评估授予内存的先后次序。

is_next_candidate列标识出下一下被唤醒的正在等待的查询。

sys.dm_os_wait_stats

此DMV返回显示所有服务器对象的等待统计信息。内存授予的等待类型叫做“RESOURCE_SEMAPHORE”.如果此等待类型过多,则可能是大型查询引起的。

  使用示例

查询内存队列中正在等待的查询:

SELECT * FROM sys.dm_exec_query_memory_grants where grant_time is null

查询谁使用最多查询内存授予:

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)

查询缓存中使用查询内存授予的查询:

SELECT t.text, cp.objtype,qp.query_plan
             FROM sys.dm_exec_cached_plans AS cp
            JOIN sys.dm_exec_query_stats AS qs ON cp.plan_handle = qs.plan_handle
            CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
            CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS t
           WHERE qp.query_plan.exist('declare namespace n="http://schemas.microsoft.com/sqlserver/2004/07/showplan"; //n:MemoryFractions') = 1

  总结:

1. 原文地址:Understanding SQL server memory grant

2. 我是在看过ShanksGao的这篇博文后,找到这个资料脑补的.

3. 大型查询,特别是大型统计查询,肯定会有排序和哈希操作,而且是最消耗资源的操作。理解查询内存授予有助于判断必要性和优化这种查询。

理解SQL Server的查询内存授予(译)的更多相关文章

  1. 理解SQL Server是如何执行查询的 (2/3)

    查询执行的内存授予(Query Execution Memory Grant) 有些操作符需要较多的内存才能完成操作.例如,SORT.HASH.HAS聚合等.执行计划通过操作符需要处理数据量的预估值( ...

  2. T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他

    简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索 ...

  3. T-SQL查询进阶--理解SQL Server中索引的概念,原理

    简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,sql server仍然可以实现应有的功能,但索引可以在大多数情况下提升查询性能,在OLAP(On line Trans ...

  4. 理解SQL Server中索引的概念

    T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他   简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能 ...

  5. 转载 50种方法优化SQL Server数据库查询

    原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1 ...

  6. 理解SQL Server中索引的概念,原理

    转自:http://www.cnblogs.com/CareySon/archive/2011/12/22/2297568.html 简介 在SQL Server中,索引是一种增强式的存在,这意味着, ...

  7. 理解SQL SERVER中的逻辑读,预读和物理读

    转自:https://www.cnblogs.com/CareySon/archive/2011/12/23/2299127.html 在我的上一篇关于SQL SERVER索引的博文,有圆友问道关于逻 ...

  8. [SQL] 理解SQL SERVER中的逻辑读,预读和物理读

    SQL SERVER数据存储的形式 在谈到几种不同的读取方式之前,首先要理解SQL SERVER数据存储的方式.SQL SERVER存储的最小单位为页(Page).每一页大小为8k,SQL SERVE ...

  9. C#构造方法(函数) C#方法重载 C#字段和属性 MUI实现上拉加载和下拉刷新 SVN常用功能介绍(二) SVN常用功能介绍(一) ASP.NET常用内置对象之——Server sql server——子查询 C#接口 字符串的本质 AJAX原生JavaScript写法

    C#构造方法(函数)   一.概括 1.通常创建一个对象的方法如图: 通过  Student tom = new Student(); 创建tom对象,这种创建实例的形式被称为构造方法. 简述:用来初 ...

随机推荐

  1. 【Cocos2d-x】VS2012开发2dx无法解析的外部符号解决记录(第一篇)【转】

    come from http://acoder.me/cocos2d-unresolved-external-symbol.html 看到cocos2d-x带了扩展包,心动的想尝试下,以下分享下我使用 ...

  2. 使用 Express 和 waterline 创建简单 Restful API

    这几篇都是我原来首发在 segmentfault 上的地址:https://segmentfault.com/a/1190000004996659  突然想起来我这个博客冷落了好多年了,也该更新一下, ...

  3. Linux2.6 内核的 Initrd 机制解析(转)

    from: https://www.ibm.com/developerworks/cn/linux/l-k26initrd/ 简介: Linux 的 initrd 技术是一个非常普遍使用的机制,lin ...

  4. 面包板入门电子制作(class1)视频 全套30集高清

    面包板入门电子制作(class1)套件(30集高清) 本套件以电子制作中最基础的元器件在面包板上搭建电路,用启发性的视频教学方式,使学习者熟悉电子电路基础.发挥想像力.在创新设计和制作中学会独立设计和 ...

  5. 如何做一份能忽悠投资人的PPT

    游侠近日发布的一款电动汽车引发全民吐槽,被人们嘲讽为“靠一份PPT忽悠投资人”.这类情形可以回溯至去年的锤子手机发布会.如今,吐槽的开始散去,我们可以静下心来吸收点干货,我们对比了锤子手机发布会的PP ...

  6. 阿里大鱼.net core 发送短信

    阿里大鱼还未提供 .net core 版SDK,但提供了相关API,下面是.net core版实现,只是简单发送短信功能: using System; using System.Collections ...

  7. phpMyAdmin在Mac OS X上的配置和使用

    本文主要记录phpMyAdmin在Mac OS X上的配置和使用,避免朋友们走弯路,浪费不必要的时间.   1. 下载:    2. 在"设置"中打开" web shar ...

  8. 修改 Semantic UI 的默认字体

    Semantic UI 默认使用的是谷歌提供的字体,并且是直接使用了谷歌的官方链接.由于大家都知道的原因,谷歌网站在国内访问速度很差,甚至根本无法访问,还有就是可能会在离线环境下使用 Semantic ...

  9. Rhino -- 基于java的javascript实现

    http://www.cnblogs.com/cczw/archive/2012/07/16/2593957.html

  10. CSS3绘制旋转的太极图案(一)

        实现步骤: 基础HTML: <div class="box-taiji"> <div class="circle-01">< ...