1.前言

对于数据库引擎来说,内存是一个性能提升的重要解决手段。把数据缓存起来,可以避免在查询或更新数据时花费多余的时间,而这时间通常是从磁盘获取数据时用来等待磁盘寻址的。把执行计划缓存起来,可以避免重复分析执行计划时带来额外的CPU及各种资源的开销。通过在内存中开辟查询内存空间,可以迅速地完成排序、哈希等计算,达到快速返回运算结果的目的。若没有足够的内存空间,数据库引擎将无法快速地响应用户的请求。

2.SQL Server如何从操作系统层面分配内存

SQL Server存储引擎本身是一个Windows下的进程,所以SQL Server使用内存和其它Windows进程一样,都需要向Windows申请内存(通过VirtualAlloc之类的API向Windows申请内存)。

3.物理内存、虚拟内存、虚拟内存管理器

3.1物理内存(RAM)

内存芯片提供的物理存储空间,能被CPU直接访问,访问速度快,易丢失。内存性能指标GB/s,ns(纳秒),前者是吞吐量,后者是响应时间。磁盘性能指标MB/s,us(微秒),从两者对比就能看出内存访问速度是远优于磁盘的。

3.2虚拟内存

物理内存容量是有限的,如果所有进程都直接使用有限的物理内存,那新的进程将无法为他们找到任何物理内存,那么物理内存将容易成为瓶颈。所以Windows会授予每个进程一个虚拟地址空间(Virtual Address Space,VAS),通过VAS建立应用程序与物理内存的桥梁。

3.2.1虚拟地址空间(Virtual Address Space,VAS)

是指一个应用程序能够申请访问的最大地址空间。VAS作为中间的抽象层的,不是所有的请求都直接映射到物理内存,它首先映射到VAS,然后映射到物理内存。
而两个进程可以共用一个VAS,而VAS的大小取决于CPU架构,具体请看下面表格:

OS Type

Kernel Model

(内核模式)

User Model

(用户模式)

Total

32位系统

2GB

2GB

4GB

64位系统

8TB

8TB

16TB

VAS有两种内存模式,Kernel Model和User Model。Kernel Model下的VAS是供Windows系统进程使用,而User Model下的VAS是供用户进程使用。
由表格可知,32位Windows系统应用程序可以访问最大2GB的VAS,64Windows位系统可以访问最大8TB的VAS。这意味着在32位Windows系统中一个word文档进程跟一个SQL Server进程能得到最大2GB的VAS是一样的。因此,从理论上讲,这意味着任何应用程序进程在32位Windows系统上都将共享最大限度的2 G的VAS。

3.3虚拟内存管理器(Virtual Memory Manager,VMM)

VMM是负责把物理内存在系统中所有需要内存的进程之间作共享,必要时会从VAS回收物理内存,把数据存储到页面文件上面去,保证数据永不丢失。当进程需要内存时,VMM会从页面文件中查找数据,并将这数据写入一部分空闲内存当中,然后将新页面映射到需要操作的VAS当中。

4.SQL Server内存架构

SQL Server 2012对内存管理这块跟SQL Server 2008还是有比较大的区别的,参考一些资料,下面我们来看看两者具体架构。

SQL Server 2008 R2:                                                                                     SQL Server 2012:

名词术语

4.1缓冲池(Buffer Pool)

为了更加清楚了解Buffer Pool,我们先来了解下 SQL Server的所需要的内存有哪些,其中包括SQL Server服务(sqlserver.exe)和其它一些组件所占用的内存,例如SQL Server代理程序(sqlagent.exe), SQL Server复制代理程序、SQL Server报表服务(ReportingServicesService.exe)、SQL Server Analysis Services(msmdsrv.exe)、SQL Server Integration Services(MsDtsSrvr.exe),和SQL Server 全文搜索(msftesql.exe)。
在一台运行SQL Server的服务器上,运行着sqlserver服务(sqlserver.exe)和其它一些组件。在sqlserver服务(sqlserver.exe)获取到的内存中,又分为2大块:一部分为Buffer Pool,另一部分为非Buffer Pool,旧称MemToReserve(默认sqlserver.exe给它预留了256MB)。下表为这两部分内存各自的用途:

SQL Server 进程所占内存

Buffer Pool

EXEC sp_configure N'min server memory

EXEC sp_configure N'max server memory

非Buffer Pool(即MemToReserve)

(默认为256MB), 可以sqlserver.exe启动时加-g参数,预留足够内存(预留内存大小=256MB+工作线程数*512KB)

Buffer Pool中主要存放之前查询中的数据页,和索引页。然后根据它自已的算法,自动清理过期过访问或效率低下的页。

SQL Server工作线程

占用不多

分布式查询引用的OLE DB访问接口

如操作链接服务器

备份还原

维护计划或者T-SQL备份恢复

扩展过程

如sp_或sys开头的系统存储过程,sp_OACreate 存储过程

多页的分配器SQL Server内存管理器

如.net framework程序(它们连接sqlserver的网络包大小为8K, sqlserver默认网络包大小为4k)

.DLL文件

SQL Server CLR的Microsoft COM对象

 

4.2 Single-Page

这块内存是<=8kb的存储,适用于sql server 2008及以前,属于Buffer Pool缓冲池来分配。有存储数据页面,Consumer功能组件。

4.3 Multi-Page

这块内存是>8kb的存储,适用于sql server 2008及以前,不属于Buffer Pool缓冲池来分配, 有存储Consumer功能组件, 第三方代码, Threads线程。

4.4 Any Size Page

这个适用于sql server 2012及以上,整合了single-page,multi-page统称any size page。

4.5 Memory Manager

它来统一响应SQL Server 内部各种组件内存申请的请求。因为这个原因,在SQL Server 2012里面,max server memory 不再像以前的版本那样,只控制buffer pool的大小,也包括那些大于8kb 的内存请求。也就是,max server memory能够更准确地控制SQL Server 的内存使用了。

5.SQL Server 2008内存

从内存架构我们可以看到有page reservation需预先申请的内存,有momory objects从windows api申请的内存,有clr第三方申请的内存。

内存使用分类

5.1按用途分类

(1)Database Cache(数据页面缓冲区)

存放数据页面的缓冲区。SQL Server数据库里的数据都是以8KB为一个页面存储。当有用户需要使用到这个页面上存储的数据时,SQL Server会把整个页面都调入内存,供用户使用。所以8KB是数据访问的最小单元。当用户修改了某个页面上的数据时,SQL Server会在内存中将这个页面修改,但是不会立刻将这个页面写回磁盘,而是等到后面的Checkpoint或Lazy Write的时候集中处理。
(2)各类Consumer
SQL Server的很多功能组件,都必须要申请内存来完成它们的任务。这些统称为“Consumer”。常见有如下:
Connection:SQL Server为每个连接分配一个数据结构,存储关于这个连接的信息。另外,还会分配一个输入缓冲池,缓冲客户端发来的指令;一个输出缓冲池,存放SQL Server返回的结果,等待客户端取走。
General:一组大杂烩。包括语句的编译、范式化、每个锁数据结构、事务上下文、表格和索引的元数据等。
Query Plan:语句和存储过程的执行计划。和Database Cache类似,如果SQL Server没有内存压力,它就会保留每一个生成的执行计划,供以后的用户重用,减少Comlile的消耗。所以Query Plan也会是一块比较大的内存使用区域。
Optimizer:SQL Server在生成执行计划的过程中需要消耗的内存。
Utilities:像BCP、Log Manager、Parallel Queries、Backup等比较特殊的操作需要的内存。
(3)线程内存
SQL Server会为每个进程内的每个线程分配0.5MB的内存,以存放线程的数据结构和相关信息。
(4)第三方代码申请的内存(COM,XP...)
在SQL Server的进程里,会运行一些非SQL Server自身的代码。例如,用户定义的CLR或者Extended Stored Procedure代码,Linked Server需要加载的数据连结驱动,调用SQL Mail功能需要加载的MAPI动态库等。这些代码也会申请内存,会算在SQL Server自己都不知道。

5.2按申请方式分类

有些SQL Server内存的申请方式,是预先Reserve一块大的内存,然后在使用的时候一小块一小块地Commit。而另外的内存申请则直接从空间里Commit。在SQL Server里,把后一种方式叫Stolen。
在SQL Server里,对Database Cache,SQL Server会先Reserve,再Commit。其他的所有内存使用,基本都是直接Commit,都是“Stolen”。要重申的是,Stolen内存也是正常使用的内存,不是泄漏掉的内存。
之所以要把这两种分开,是因为SQL Server不会对Stolen的内存使用AWE功能。也就是说,AWE扩展出去的内存,只能用来存放Database Cache。其他内存还要在原来的那2GB里想办法。

5.3按申请大小分类

对于SQL Server自己申请的内存,有两种内存申请单位。
小于等于8KB一个单位内存申请,SQL Server就分配一个8KB页面。所有这些页面都集中管理,这块内存被称为Buffer Pool。一次一个页面的这种分配称为Single Page Allocation。
对于大于8KB为单位的内存申请,SQL Server把它们集中在另外一个区域,称为Multi-Page Allocation(旧称MemToLeave)。而这种分配称为Multi-Page Allocation。

5.4各个内存分类方法之间的关系:

类型

Database Cache

Consumer

3rh Party Code

Threads

Reserved/Commit

一般不是

一般不是

不是

Stolen

不是

Buffer Pool

(Single Page)

所有

绝大部分

没有

没有

MemToLeave(Multi-Page)

没有

一小部分

所有

所有

这里的一个例外是运行在SQL Server进程里的CLR代码所申请的内存。这部分内存像第三方代码一样,也是使用MemToLeave的内存。但是,CLR可能也会用Reserve-Commit的方式申请内存。所以MemToLeave的内存也并不是都是Stolen的。

6.SQL Server 2012内存

根据SQL Server内存架构图,我们可以知道,在2012版本上,Single Page Allocation跟Multi-Page Allocation合并为Any Size Page Allocation了。而max server memory控制的不但是 Buffer Pool内存大小,而是所有大于等于小于8KB的内存请求。
如图:

比如我设置最小服务器内存为8G,重新启动下SQL Server (MSSQLSERVER)服务,再使用dmv来查看当前实例的总内存空间,以及占用内存空间:
--Target Server Memory (KB)最多能申请的内存量
--Total Server Memory (KB)目前使用了多少内存量
SELECT counter_name, ltrim(cntr_value*1.0/1024.0/1024.0)+'G'
AS memoryGB FROM sys.dm_os_performance_counters
WHERE counter_name like '%target%server%memory%'or counter_name like '%total%memory%'

从查询结果可以看到当我们在SQL Server设置最小服务器内存为8G的时候,给SQL Server分配了多少内存,它就占用多少多少内存,从而达到性能最佳。

7.总结

这是我初次学习SQL Server性能调优方面的知识,谢谢博友花阴偷移指点。很多知识点方面可能理解有偏差,希望各个路过大神指点一二。

参考文献:
Microsoft.SQL.Server企业级平台管理实践
SQL Server 2012 内存管理 (memory management) 改进

(1)SQL Server内存浅探的更多相关文章

  1. SQL Server内存遭遇操作系统进程压榨案例

    场景: 最近一台DB服务器偶尔出现CPU报警,我的邮件报警阈(请读yù)值设置的是15%,开始时没当回事,以为是有什么统计类的查询,后来越来越频繁. 探索: 我决定来查一下,究竟是什么在作怪,我排查的 ...

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

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

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

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

  4. SQL SERVER 内存学习系列(一)

    最近帮客户解决发布订阅的问题时,突然遇到这样一个问题发布订阅中报下面的错误,另外执行alter table 操作时也会报错 : 问题很奇怪发布订阅和CLR有什么关系?memtoleave内存是个啥?回 ...

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

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

  6. SQL Server内存理解的误区

    SQL Server内存理解 内存的读写速度要远远大于磁盘,对于数据库而言,会充分利用内存的这种优势,将数据尽可能多地从磁盘缓存到内存中,从而使数据库可以直接从内存中读写数据,减少对机械磁盘的IO请求 ...

  7. SQL SERVER 内存分配及常见内存问题 DMV查询

    内存动态管理视图(DMV): 从sys.dm_os_memory_clerks开始. SELECT  [type] , SUM(virtual_memory_reserved_kb) AS [VM R ...

  8. SQL SERVER 内存分配及常见内存问题 简介

    一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解SQL SERVER与windows是如何协调.共享内存.并且SQ ...

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

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

随机推荐

  1. linux中的目录

    Linux文件系统数如下: 在 Linux 系统中,文件系统通过目录"包含"子目录及文件的方式,来组织成一个树状结构.那么目录到底是如何"包含"其他目录及文件的 ...

  2. 关于m3u8文件, ts文件解密, hls 解密. 一些记录

    使用openssl 解密 openssl aes-128-cbc -d -in 原.ts -out 解密后.ts -nosalt -iv 偏移量 -K key16进制 其中 iv 偏移量和 key 一 ...

  3. 第08组 Alpha冲刺(6/6)

    队名:955 组长博客:https://www.cnblogs.com/cclong/p/11913269.html 作业博客:https://edu.cnblogs.com/campus/fzu/S ...

  4. ajax下post提交方式下载文件的处理(转)

    ajax是不能直接下载文件的,所以一般都是通过一个超链接的形式去下载一个文件 但是当牵扯到需要发送很多数据到服务器上再下载的时候超链接的形式就有些不好看了, /*=================== ...

  5. 必会的 55 个 Java 性能优化细节!一网打尽!

    阅读本文大概需要 10 分钟. 来源:https://yq.aliyun.com/articles/662001 在 Java 程序中,性能问题的大部分原因并不在于 Java 语言,而是程序本身.养成 ...

  6. list删除、集合遍历删除

    public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); li ...

  7. 让ie10/11支持非单页面的vue/es6

    为了满足某些客户的要求,最近让前端同学实现了ie 10(windows 7)/11(windows 10)支持多页面的vue/es6,基本参考如下: https://www.cnblogs.com/n ...

  8. electron-vue在使用element-ui时部分组件无法显示问题

    原文连接: https://juejin.im/post/5d132629e51d45772a49ad71 问题描述 在使用electron开发桌面系统时,遇到部分element-ui组件在页面中无法 ...

  9. Heartbeat took longer than "00:00:01" at "09/06/2019 05:08:08 +00:00".

    .netcore在k8s+docker+linux,部署后,偶尔会报这样的警告 Warn:Microsoft.AspNetCore.Server.KestrelHeartbeat took longe ...

  10. 查找算法(5)--Tree table lookup--树表查找

    1.树表查找 (1) 最简单的树表查找算法——二叉树查找算法. [1]基本思想:二叉查找树是先对待查找的数据进行生成树,确保树的左分支的值小于右分支的值,然后在就行和每个节点的父节点比较大小,查找最适 ...