理解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(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. 大型查询,特别是大型统计查询,会有很排序和哈希操作,并且是最消耗资源的操作。理解查询内存授予有助于判断必要性和优化这种查询。

时间: 2024-12-31 06:29:04

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

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

简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索引的概念,需要了解大量原理性的知识,包括B树,堆,数据库页,区,填充因子,碎片,文件组等等一系列相关知识,这些知识写一本小书也不为过.所以本文并不会深入讨论这些主题. 索引是什么 索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息. 精简来说,索引是一种结构.

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

SQL SERVER数据存储的形式 在谈到几种不同的读取方式之前,首先要理解SQL SERVER数据存储的方式.SQL SERVER存储的最小单位为页(Page).每一页大小为8k,SQL SERVER对于页的读取是原子性,要么读完一页,要么完全不读,不会有中间状态.而页之间的数据组织结构为B树(请参考我之前的博文).所以SQL SERVER对于逻辑读,预读,和物理读的单位是页. SQL SERVER一页的总大小为:8K 但是这一页存储的数据会是:8K=8192字节-96字节(页头)-36字节(

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

原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6.查询出的数据量过大(可以采用多次查询,其他的方法降低数据量) 7.锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷

理解SQL SERVER中的分区表(转)

简介 分区表是在SQL SERVER2005之后的版本引入的特性.这个特性允许把逻辑上的一个表在物理上分为很多部分.而对于SQL SERVER2005之前版本,所谓的分区表仅仅是分布式视图,也就是多个表做union操作. 分区表在逻辑上是一个表,而物理上是多个表.这意味着从用户的角度来看,分区表和普通表是一样的.这个概念可以简单如下图所示: 而对于SQL SERVER2005之前的版本,是没有分区这个概念的,所谓的分区仅仅是分布式视图: 本篇文章所讲述的分区表指的是SQL SERVER2005之

SQL Server资源管理之内存管理篇(下)

在上篇文章SQL Server资源管理之内存管理篇(上),介绍了SQL Server的内存管理的一些理论知识,这篇利用这些知识来解决现实中常见的一些问题. 一.数据页缓存压力的调优 前篇我们说过,如果用户访问的数据页面都缓存在内存里,这样的相应速度是最快的.但是现实中,数据库的大小都是大于物理内存的,SQL Server不可能将用户需要的所有数据都缓存在内存中,当用户需要的数据不在内存中,将会发生Paging动作从硬盘中读取需要的数据,偶尔的Paging不会从整体上影响SQL Server的性能

SQL Server资源管理之内存管理篇(上)

对SQL Server来说,最重要的资源是内存.Disk和CPU,其中内存又是重中之重,因为SQL Server为了性能要求,会将它所要访问的数据全部(只要内存足够)放到缓存中.这篇就来介绍SQL Server的内存管理体系. SQL Server作为Windows上运行的应用程序,必须接受Windows的资源管理,利用Windows的API来申请和调度各类资源.但是,由于Windows的资源管理体系,是为了满足大多数的应用程序所设计的,这对于SQL Server这种定位于企业级.支持多用户和高

优化SQL Server数据库查询方法

SQL Server数据库查询速度慢的原因有很多,常见的有以下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6.查询出的数据量过大(可以采用多次查询,其他的方法降低数据量) 7.锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷) 8.sp_lock,sp_who,活动的用户查看,原因是读写竞争资源. 9.返回了不必要的行和列 10.查询语句不好,没有优

SQL Server数据库查询速度慢的原因和解决方法

问 SQL Server数据库查询速度慢的原因有很多,常见的有以下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6.查询出的数据量过大(可以采用多次查询,其他的方法降低数据量) 7.锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷) 8.sp_lock,sp_who,活动的用户查看,原因是读写竞争资源. 9.返回了不必要的行和列 10.查询语句不好,没

[转]如何将SQL Server表驻留内存和检测

注意这个功能在SQL2005后已经废弃,因为SQL2005会自动管理哪些表常驻内存. 将SQL Server数据表驻留内存是SQL Server提供的一项功能,在一般小型系统的开发过程中估计很少会涉及到.这里整理了相关文档资料,演示如何把SQL Server中一个表的所有数据都放入内存中,实现内存数据库,提高实时性. 1, DBCC PINTABLE Marks a table to be pinned, which means Microsoft SQL Server does not flu