设为首页 收藏本站
查看: 1115|回复: 0

[经验分享] 理解SQL Server的查询内存授予

[复制链接]

尚未签到

发表于 2018-10-18 10:49:37 | 显示全部楼层 |阅读模式
  此文描述查询内存授予(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中的标记部分内容,获取更多内存使用的信息。
并行度依赖(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(23bit SQL 200为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. 大型查询,特别是大型统计查询,肯定会有排序和哈希操作,而且是最消耗资源的操作。理解查询内存授予有助于判断必要性和优化这种查询。
  -------------------------------------
  作者:Joe.TJ


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-623108-1-1.html 上篇帖子: hibernate cglib enhancement exception during deployment on JES application serve 下篇帖子: 【zabbix】zabbix server安装
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表