理解SQL Server的查询内存授予(译)
此文描述查询内存授予(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的查询内存授予(译)的更多相关文章
- 理解SQL Server是如何执行查询的 (2/3)
查询执行的内存授予(Query Execution Memory Grant) 有些操作符需要较多的内存才能完成操作.例如,SORT.HASH.HAS聚合等.执行计划通过操作符需要处理数据量的预估值( ...
- T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他
简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索 ...
- T-SQL查询进阶--理解SQL Server中索引的概念,原理
简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,sql server仍然可以实现应有的功能,但索引可以在大多数情况下提升查询性能,在OLAP(On line Trans ...
- 理解SQL Server中索引的概念
T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他 简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能 ...
- 转载 50种方法优化SQL Server数据库查询
原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1 ...
- 理解SQL Server中索引的概念,原理
转自:http://www.cnblogs.com/CareySon/archive/2011/12/22/2297568.html 简介 在SQL Server中,索引是一种增强式的存在,这意味着, ...
- 理解SQL SERVER中的逻辑读,预读和物理读
转自:https://www.cnblogs.com/CareySon/archive/2011/12/23/2299127.html 在我的上一篇关于SQL SERVER索引的博文,有圆友问道关于逻 ...
- [SQL] 理解SQL SERVER中的逻辑读,预读和物理读
SQL SERVER数据存储的形式 在谈到几种不同的读取方式之前,首先要理解SQL SERVER数据存储的方式.SQL SERVER存储的最小单位为页(Page).每一页大小为8k,SQL SERVE ...
- C#构造方法(函数) C#方法重载 C#字段和属性 MUI实现上拉加载和下拉刷新 SVN常用功能介绍(二) SVN常用功能介绍(一) ASP.NET常用内置对象之——Server sql server——子查询 C#接口 字符串的本质 AJAX原生JavaScript写法
C#构造方法(函数) 一.概括 1.通常创建一个对象的方法如图: 通过 Student tom = new Student(); 创建tom对象,这种创建实例的形式被称为构造方法. 简述:用来初 ...
随机推荐
- Apache Storm 与 Spark:对实时处理数据,如何选择【翻译】
原文地址 实时商务智能这一构想早已算不得什么新生事物(早在2006年维基百科中就出现了关于这一概念的页面).然而尽管人们多年来一直在对此类方案进行探讨,我却发现很多企业实际上尚未就此规划出明确发展思路 ...
- 最近读的javascript,一些文章
本帖子是记录一些javascript的一些文章: 1. 理解node.js 2.异步编程 http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF% ...
- AWVS漏洞测试-01节-AWVS的主要作用
AWVS漏洞工具简单介绍 AWVS全称: Acunetix Web Vulnerability Scanner 中文翻译就是:Acunetix网站攻击扫描器 扫描网站漏洞,通过网络爬虫Crawler的 ...
- [转] The program can't start because api-ms-win-crt-runtime-l1-1-0.dll is missing
https://www.smartftp.com/support/kb/the-program-cant-start-because-api-ms-win-crt-runtime-l1-1-0dll- ...
- Android开发(二十五)——Android上传文件至七牛
设置头像: Drawable drawable = new BitmapDrawable(dBitmap); //Drawable drawable = Drawable.createFromPath ...
- 菜鸟学JS(四)——javascript为按钮注册回车事件(设置默认按钮)
不得不说,在JS方面,自己真的是个不折不扣的菜鸟.对于JS以及一些JS框架如JQuery等JS框架,自己也只是处在简单应用的阶段,当然自己也在不断的学习当中,希望将来能跟大家分享更多JS方面的心得.今 ...
- GameOver
GameOver. 正了八经的觉得GameOver了.该开始新的了.
- 阅读《Effective C++》系列
<Effective C++>条款07:为多态基类声明virtual析构函数 这样做主要是为了防止内存泄漏,见我hexo博客. C++的虚析构函数 <Effective C++> ...
- iOS10 升级兼容必备参考
最近提交审核不通过,再iOS10上运行崩溃 .然后需要处理崩溃的问题,晚上找了一下,整理收集起来. 方便后续查看使用. 以下参考链接特别有用: http://blog.csdn.net/gbking/ ...
- IT战略规划咨询
目录 1IT战略规划微咨询简介 2IT战略的意义 3服务模式 4IT战略规划焦点问题 5IT战略规划步骤 6服务提供方微咨询网 7微咨询价值 8微咨询服务方式 9IT工作规划与IT战略规... IT战 ...