原文出处:https://blogs.msdn.microsoft.com/sqlmeditation/2013/01/01/memory-meditation-the-mysterious-sql-server-memory-consumer-with-many-names/

对于多个不同名称的内存消费者

你曾经是否想知道内存授予是什么(Memory grants )?
什么是查询执行的保留(预定)内存(QE Reservations)?
以及查询执行内存(Query Execution Memory)?
工作空间内存(Workspace memory),以及内存保留(译者注:很多地方都将Reservations译作“保留”,个人认为译作“预定”一次更为容易理解,下文中预定同义与“保留”)

就好比生活中的许多事情一样,简而言之,一句话:所以的名字都指向SQL Server中的同一个内存消费者,
查询期间的为了排序或者哈希操作(包括bulk copy和索引创建等)的内存分配
请允许我引申出来更大的话题,在一个查询执行的过程中,这个查询可能会从不同的"buckets" 或者 clerks中申请内存,(从不同地方申请内的差异)依赖于申请的内存用来做什么。
例如,一个查询在最初的解析和编译时,他需要消费编译或者是优化内存。一旦查询语句编译完成之后,他所申请的内存就会释放,
同时其对应的查询执行计划会被缓存,为此,这个执行计划会消费过程缓存内存,并且这块内存一直被占用直到服务器重启或者内存发生压力,此时,查询准备好执行。
如果查询语句发生排序或者哈希操作(连接或者组合),那么它首选会使用实现预定的内存用来存储结果或者存储Hash桶(的结果)
这个部分内存发生在查询执行期间,具体会涉及到很多内存的名称。

术语和故障诊断工具

让我们回顾一下您可能会遇到的关于这个内存消耗者的不同类别。
同样,所有这些描述了与相同内存分配相关的概念:

查询执行内存 (QE Memory):
  这一项是用来强调在查询执行过程中sort/hash内存使用这个事实,同时也是查询执行期间的最大的内存消费部分。

查询内存(QE)预定或者内存预定:
  当一个查询需要sort/hash操作准备内存的时候,在执行期间,他将基于包含了sort或者hash运算的原始查询计划,执行一个内存保留请求(内存预定请求),
  然后查询开始执行,他请求内存,同时sqlserver将会授予这个查询部分或者是全部的内存请求,主要是依赖于服务器可用内存
  有一个叫做MEMORYCLERK_SQLQERESERVATIONS的内存clerk,这个内存计数器来保留这部分内存的分配的情况。

  ------------------------------译者注---------------------------------
  这部分内存可以从sys.dm_os_memory_clerks中查询出来,如下截图是一个存在负载的服务器的服务器上的MEMORYCLERK_SQLQERESERVATIONS分配情况
  可见这部分内存还是不小的,这里是有超过4GB的MEMORYCLERK_SQLQERESERVATIONS(服务器内存32GB)
  如果一个服务器没有负载的时候,这个内存的使用是很低的,甚至可以是0

  

  --------------------------------------------------------------------------

内存授予(Memory Grants):
  当SQL Server给一个请求授予请求内存的时候,称之为内存授予发生了,
  有一个性能计数器保留了已经有多少内存授予了请求内存:Memory Grants Outstanding
  另外一个计数器表明有多少查询已经请求了sort/hash内存,但是出于等待状态,因为查询执行内存已经耗尽:Memory Grants Pending
  这两个内存计数器显示了内存授予和内存授予的不足,也就是说,一个单独的查询可能消耗4GB的内存去执行一个排序,但这两种情况都不会被反映出来

  ------------------------------译者注---------------------------------
  这部分内存可以理解为实时请求内存,SQL Server实时请求越多,这部分内存就越大,
  比如一个Session需要20MB的运行内存,同时运行10个Session就需要200MB,同时运行100个Session就需要2000MB,当然每个Session需要的运行内存都不一样(memory grant),这里仅仅是举例
  可以从sys.dm_os_memory_clerks中查询出来,如下截图是一个存在负载的服务器的服务器上的MEMORYCLERK_SQLQERESERVATIONS分配情况
  可见这部分内存还是不小的,这里是有超过4GB的MEMORYCLERK_SQLQERESERVATIONS(服务器内存32GB)
  如果一个服务器没有负载的时候,这个内存的使用是很低的,甚至可以是0
  Memory Grants Outstanding某一个Session无法得到其申请的内存,处于等待内存状态,
  SQL Server是一个自我调节(self tuning)引擎,这部分内存一般会预留的足够,正常情况下不会发生因为sql的执行缺少内存而等待的情况
  凡事得分清楚轻重缓急,内存也一样分为急需的和非急需的,不能那边为了缓存数据而占据内存,而这边连实时的请求都无法响应吧。
  举个不恰当的例子,再穷,可以不买房不买车,总的留够吃饭的钱吧。
  其他地方的内存可以存在压力(比如数据缓存可能快速地被置换出内存),但是面对相应实时请求的内存,SQL Server留的还是比较充足的,个人很少见到因为Session等待内存而无法执行的情况。
  但是话不能反过来说,不能说没有出现Memory Grants Pending,就说明内存没有压力。

  

  ----------------------------------------------------------------------------

为了观察单独的请求和他们已经申请的内存,你可以查询sys.dm_exec_query_memory_grants这个DMV
这个DMV显示的是当前运行的查询的内存授予情况,而非历史情况
另外,你可以捕获实际查询执行计划,查询其一个叫做Query plan的XML节点,他包含了内存授予的大小,
如下示例:
<QueryPlan DegreeOfParallelism="8" MemoryGrant="2009216"
另外一个DMV是 sys.dm_exec_requests,包含了一个叫做granted_query_memory的8kb为单位的列,
比如一个1000的值,意味着1000*8kb,或者说是8000kb的内存授予

工作空间内存(Workspace Memory):

  这仍旧是另外一个描述同样内存的项目,
  你经常会看到这个性能技术区授予Workspace Memory (KB),反映的是当前所有用来sort/hash操作的内存使用
  最大工作空间内存(Maximum Workspace Memory (KB))数量是自SQL Server启动以来的最大的工作空间内存。
  在我看来,工作空间内存项目是一个用来描述sqlserver7.0个sqlserver2000的内存分配的一个遗留问题,在SQLServer2005以后已经作废

资源信号量(Resource Semaphore):
  为了给这个概念增加更多的复杂性,SQL Server使用一个称作信号量(semaphore)的线程同步对象来跟踪有多少已经被授予了的内存。
  想法是这样的:如果sqlserver用光了workspace memory/QE memory, 那么使用out-of-memory错误来替代查询执行失败(不是直接反馈查询失败,而是等待内存)
  它会促使查询等待可用内存,然后(得到可用内存之后)可以重新执行

  在这个过程中,Memory Grants Pending 性能计数器开始变得有意义。
  因此会在sys.dm_exec_query_memory_grants中生成wait_time_ms,granted_memory_kb = NULL, timeout_sec
  顺便说一下,这个和编译内存是在SQL Server中仅有的在内存不足的情况下,会执行等待内存的两种内存。
  在其他情况中,查询将会直接失败并报出701错误--内存不足。

在SQL Server中另外一种等待类型也昭示着一个查询是在等待内存授予--RESOURCE_SEMAPHORE
正如文档中所说的,这种情况发生,一个查询内存无法被立即授予归结于其他并发执行的查询。
频繁的等待和等待时间可能预示这个过多的并发查询,或者是过多的内存授予数量。
你可以在sys.dm_exec_requests这个DMW中观察Session级别的等待

为什么需要关注Memory Grants 或者 Workspace Memory 或者 Query Execution Memory或者不管你怎么称呼它。

过去几年对于性能问题的诊断过程中,我发现这是最常见的内存相关问题之一,应用程序经常执行一些看起来相当简单的查询,
却因为上执行大量的Sort或者hash操作而遭受到大量的性能破坏
那些查询不仅仅是在执行过程中消耗大量的内存,并且也会导致其他查询等待内存,这就是性能瓶颈。

使用上述我提供的工具(DWVs,性能计数器和实际执行计划),你可以查出来哪个查询是耗费了大量的内存,然后再考虑优化/重写的可能性

Sort/Hash操作产生的情景

提及查询重写,这里有一些可能会导致大量内存授予的情况

Sort操作产生的原因(包括但不限于以下几种情况)
  ORDER BY (T-SQL)
  GROUP BY (T-SQL)
  DISTINCT (T-SQL)
  Merge join操作是优化器选择的,其中合并联接的一个输入必须被排序

Hash Match操作产生的原因(包括但不限于以下几种情况)
  JOIN (T-SQL) – 如果SQL选择执行一个Hash操作,典型的就是缺少合理的索引导致的一个昂贵的join操作--hash join,观察执行计划
  DISTINCT (T-SQL) –Hash聚合可能会用来执行distinct操作,观察执行计划
  SUM/AVG/MAX/MIN (T-SQL)– 任何聚合操作可能会导致Hash 聚合,观察执行计划
  UNION – Hash聚合可能会用来做移除重复项

了解这些常见的原因可以帮助应用程序开发人员尽可能地消除对SQL Server的大量内存授予请求。
一如既往,基本的查询调优开始于检查查询是否有适当的索引,以帮助它们减少读取、尽可能减少或消除大型排序。

这里有个内存授予的博文供参考 http://blogs.msdn.com/b/sqlqueryprocessing/archive/2010/02/16/understanding-sql-server-memory-grant.aspx

(译)内存沉思:多个名称相关的神秘的SQL Server内存消耗者。的更多相关文章

  1. SQL Server 内存中OLTP内部机制概述(四)

    ----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...

  2. SQL Server 内存中OLTP内部机制概述(三)

    ----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...

  3. SQL Server 内存中OLTP内部机制概述(二)

    ----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...

  4. SQL Server 内存中OLTP内部机制概述(一)

    ----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...

  5. sql server 内存初探

    一. 前言 对于sql server 这个产品来说,内存这块是最重要的一个资源, 当我们新建一个会话,相同的sql语句查询第二次查询时间往往会比第一次快,特别是在sql统计或大量查询数据输出时,会有这 ...

  6. Sql Server 内存相关计数器以及内存压力诊断

    在数据库服务器中,内存是数据库对外提供服务最重要的资源之一, 不仅仅是Sql Server,包括其他数据库,比如Oracle,MySQL等,都是一类非常喜欢内存的应用. 在Sql Server服务器中 ...

  7. SQL Server 内存相关博文

    Don’t confuse error 823 and error 832 本文大意:      错误832:           A page that should have been const ...

  8. SQL SERVER 内存学习系列(二)-DMV查看内存信息

    内存管理在SQL Server中有一个三级结构.底部是内存节点,这是最低级的分配器,用于SQL Server的内存.第二个层次是由内存Clerk组成,这是用来访问内存节点和缓存存储,缓存存储则用于缓存 ...

  9. 人人都是 DBA(IV)SQL Server 内存管理

    SQL Server 的内存管理是一个庞大的主题,涉及特别多的概念和技术,例如常见的 Plan Cache.Buffer Pool.Memory Clerks 等.本文仅是管中窥豹,描述常见的内存管理 ...

随机推荐

  1. Oracle(二)在 Mysql 的基础上学习 Oracle

    毕竟我是先学的mysql,对数据库的一切认知都会有一个先入为主的思想在里面,如果不搞清楚其中的异同,我感觉Oracle我是学不会 了,甚至会把它们混淆.那么,不会mysql的没必要往下看了. 下边第一 ...

  2. 【草稿】实验室新手HandBook

    PS:本文旨在给初入CV领域实验室的新手一个可供参考的学习列表,使得能够快速熟悉常用且必要的工具.

  3. latex之矩阵表示

    $ \begin{matrix} 1 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{matrix}\quad \begin{ ...

  4. 服务器-华为RH5885 V3-安装Windows Server 2008R2后设备管理器中存在大量的感叹号,并且无法识别网络适配器,没有网卡

    问题描述:用引导盘安装Windows Server 2008R2后,出现如题的情况. 根源:驱动未安装. 解决方法: 1.下载驱动:https://support.huawei.com/enterpr ...

  5. java设计模式--UML类图

    2016-06-07 22:46:16 下面简单介绍UML类图:(图是截取的,大家可以用UML工具去画) 1.描述类的类图 类:Person 属性:name   age   sex 访问权限:-  表 ...

  6. 我发起了一个 .Net 开源 跨平台 GUI (界面开发框架)项目 HtmlCore

    大家好 , 我发起了一个 .Net 开源 跨平台 GUI (界面开发框架)项目 , 名字叫 HtmlCore  . 项目的一个主要目标是可以用 .Net 在 移动设备 上 开发 GUI 程序 (界面程 ...

  7. Java_框架面试题

    Java_框架面试题 欢迎来我Git上分享您的优秀建议 1.Spring框架分为哪七大模块,各模块的主要功能作用是什么? 七大模块,如下: 1. Spring Core: Core封装包是框架的最基础 ...

  8. 如何查看k8s存在etcd中的数据(转)

    原文 https://yq.aliyun.com/articles/561888 一直有这个冲动, 想知道kubernetes往etcd里放了哪些数据,是如何组织的. 能看到,才有把握知道它的实现和细 ...

  9. Python 面向对象(三)

    继承的实现原理 Python支持多继承 多继承的时候  属性查找的顺序 研究经典类和新式类在属性查找的不同 主要是形成菱形关系才有深度跟广度 广度优先 Python的继承原理  Python3的内置方 ...

  10. Deployment Descriptor Web.xml

    Deployment Descriptor部署描述符: - 部署描述符是要部署到Web容器或EJB容器的Web应用程序或EJB应用程序的配置文件. - 部署描述符应包含EJB应用程序中所有企业bean ...