SQL Server内存机制详解

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分配了多少内存,它就占用多少多少内存,从而达到性能最佳。

到此这篇关于SQL Server内存机制的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • SQL语句实现查询SQL Server内存使用状况

    SELECT type,--Clerk的类型 sum(virtual_memory_reserved_kb)as vm_Reserved_kb,--保留的内存 sum(virtual_memory_committed_kb)as vm_Committed_kb,--提交的内存 sum(awe_allocated_kb)as awe_Allocated_kb,--开启AWE后使用的内存 sum(shared_memory_reserved_kb)as sm_Reserved_kb,--共享的保留内

  • SQL Server 数据页缓冲区的内存瓶颈分析

    SQL Server会把经常使用到的数据缓存在内存里(就是数据页缓存),用以提高数据访问速度.因为磁盘访问速度远远低于内存,所以减少磁盘访问量同样是数据库优化的重要方面. 当数据页缓存区出现内存不足,则会出现查询慢,磁盘忙等等问题. 分析方法:主要是用到性能计数器. 查看如下性能计数器: 1. SQL SERVER:Buffer Manager-Lazy Writes/sec:内存不足则会频繁调用Lazy Writer把数数据写入磁盘,此值会经常不为0. 2. SQL SERVER:Buffer

  • SqlServer如何通过SQL语句获取处理器(CPU)、内存(Memory)、磁盘(Disk)以及操作系统相关信息

    在SQL SERVER中如何通过SQL语句获取服务器硬件和系统信息呢?下面介绍一下如何通过SQL语句获取处理器(CPU).内存(Memory).磁盘(Disk)以及操作系统相关信息.如有不足和遗漏,敬请补充.谢谢! 一:查看数据库服务器CPU的信息 ---SQL 1:获取数据库服务器的CPU型号 EXEC xp_instance_regread 'HKEY_LOCAL_MACHINE', 'HARDWARE\DESCRIPTION\System\CentralProcessor\0', 'Pro

  • 揭秘SQL Server 2014有哪些新特性(1)-内存数据库

    简介 SQL Server 2014提供了众多激动人心的新功能,但其中我想最让人期待的特性之一就要算内存数据库了.去年我再西雅图参加SQL PASS Summit 2012的开幕式时,微软就宣布了将在下一个SQL Server版本中附带代号为Hekaton的内存数据库引擎.现在随着2014CTP1的到来,我们终于可以一窥其面貌. 内存数据库 在传统的数据库表中,由于磁盘的物理结构限制,表和索引的结构为B-Tree,这就使得该类索引在大并发的OLTP环境中显得非常乏力,虽然有很多办法来解决这类问题

  • 优化SQL Server的内存占用之执行缓存

    首先说明一下SQL Server内存占用由哪几部分组成.SQL Server占用的内存主要由三部分组成:数据缓存(Data Buffer).执行缓存(Procedure Cache).以及SQL Server引擎程序.SQL Server引擎程序所占用缓存一般相对变化不大,则我们进行内存调优的主要着眼点在数据缓存和执行缓存的控制上.本文主要介绍一下执行缓存的调优.数据缓存的调优将在另外的文章中介绍. 对于减少执行缓存的占用,主要可以通过使用参数化查询减少内存占用. 1.使用参数化查询减少执行缓存

  • 浅谈SQL Server 对于内存的管理[图文]

    理解SQL Server对于内存的管理是对于SQL Server问题处理和性能调优的基本,本篇文章讲述SQL Server对于内存管理的内存原理. 二级存储(secondary storage) 对于计算机来说,存储体系是分层级的.离CPU越近的地方速度愉快,但容量越小(如图1所示).比如:传统的计算机存储体系结构离CPU由近到远依次是:CPU内的寄存器,一级缓存,二级缓存,内存,硬盘.但同时离CPU越远的存储系统都会比之前的存储系统大一个数量级.比如硬盘通常要比同时代的内存大一个数量级. 图1

  • 解决SQL Server虚拟内存不足情况

    解决SQL Server虚拟内存不足情况 症状 在具有 2 GB 或更多 RAM 的计算机上,除了 256 MB (SQL Server 7.0) 或 384 MB (SQL Server 2000) 虚拟地址空间之外,SQL Server 在启动过程中保留剩下的所有虚拟地址空间以供缓冲池使用.另外,为了存储数据和过程缓存,SQL Server 使用缓冲池内存为来自 SQL Server 进程的大多数小于 8 KB 的其他内存请求提供服务.剩下的未保留内存准备用于不能从缓冲池得到服务的其他分配.

  • SQL Server内存遭遇操作系统进程压榨案例分析

    场景: 最近一台DB服务器偶尔出现CPU报警,我的邮件报警阈(请读yù)值设置的是15%,开始时没当回事,以为是有什么统计类的查询,后来越来越频繁. 探索: 我决定来查一下,究竟是什么在作怪,我排查的顺序如下: 1.首先打开Cacti监控,发现最近CPU均值在某天之后骤然上升,并且可以看到System\Processor Queue Length 和 sqlservr\%ProcessorTime 也在显著的变化. 2.从最容易入手的低效SQL开始,考虑是不是最近业务做了什么修改?连接到该SQL

  • sql server学习基础之内存初探

    一. 前言 对于sql server 这个产品来说,内存这块是最重要的一个资源, 当我们新建一个会话,相同的sql语句查询第二次查询时间往往会比第一次快,特别是在sql统计或大量查询数据输出时,会有这么感觉.除了第一次要编译生成执行计划,  在CPU,I/O 的影响外,最主要的是第二次查询是从内存缓存中读出,为什么是这样,sql server 内存里存储了什么,它与windows内存又有什么区别?  参考了一些资料 下面来试着讲讲. 二. 内存和硬盘 为什么内存是宝贵的,在每个系统上都是有限的,

  • SQL Server内存机制详解

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

  • SQL SERVER存储过程用法详解

    目录 一.存储过程的概念 存储过程的优点 二.存储过程的分类 1.系统存储过程 2.临时存储过程 3.用户自定义存储过程 二.存储过程的用法 1.不带参数的存储过程,获取MyStudentInfo表的所有记录 2.创建带输入参数的存储过程 3.创建带默认值的输入参数的存储过程 4.创建带输出参数的存储过程(根据输入的ID返回年级ID) 5.创建带返回值的存储过程 6.创建带变量的存储过程 7.创建带输入输出参数的存储过程 8.创建分页存储过程 分页存储过程2 9.返回多个结果集 10.存储过程中

  • SQL Server COALESCE函数详解及实例

    SQL Server COALESCE函数详解 很多人知道ISNULL函数,但是很少人知道Coalesce函数,人们会无意中使用到Coalesce函数,并且发现它比ISNULL更加强大,其实到目前为止,这个函数的确非常有用,本文主要讲解其中的一些基本使用:  首先看看联机丛书的简要定义: 返回其参数中第一个非空表达式语法: COALESCE ( expression [ ,...n ] ) 如果所有参数均为 NULL,则 COALESCE 返回 NULL.至少应有一个 Null 值为 NULL

  • Java程序执行过程及内存机制详解

    本讲将介绍Java代码是如何一步步运行起来的,其中涉及的编译器,类加载器,字节码校验器,解释器和JIT编译器在整个过程中是发挥着怎样的作用.此外还会介绍Java程序所占用的内存是被如何管理的:堆.栈和方法区都各自负责存储哪些内容.最后用一小块代码示例来帮助理解Java程序运行时内存的变化. Java程序执行过程 步骤 1: 写源代码,源代码将以.java的文件格式保存在电脑硬盘中. 步骤 2: 编译器(compiler)检查是否存在编译期错误(例如缺少分号,关键字拼写错误等).若通过检测,编译器

  • Sql Server之数据类型详解

    Character 字符串: 数据类型 描述 存储 char(n) 固定长度的字符串.最多 8,000 个字符. n varchar(n) 可变长度的字符串.最多 8,000 个字符.   varchar(max) 可变长度的字符串.最多 1,073,741,824 个字符.   text 可变长度的字符串.最多 2GB 字符数据.   Unicode 字符串: 数据类型 描述 存储 nchar(n) 固定长度的 Unicode 数据.最多 4,000 个字符.   nvarchar(n) 可变

  • C#编程实现连接SQL SERVER数据库实例详解

    本文实例讲述了C#编程实现连接SQL SERVER数据库.分享给大家供大家参考,具体如下: 首先,在SQL SEVER里建立一个名为"Exercise"的数据库名,在该数据库下建立一张名为"lianxi"的表.好,现在开始写代码. 在FORM1里拖一个DATAGIRDVIEW用于显示表,在放一个BUTTON用于执行操作.加入命名空间 复制代码 代码如下: using system.data.sqlclient; private void button1_Click(

  • SQL Server 触发器实例详解

    Microsoft SQL Server™ 2000 提供了两种主要机制来强制业务规则和数据完整性:约束和触发器.触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程.触发器主要是通过事件进行触发被自动调用执行的.而存储过程可以通过存储过程的名称被调用. Ø 什么是触发器 触发器对表进行插入.更新.删除的时候会自动执行的特殊存储过程.触发器一般用在check约束更加复杂的约束上面.触发器和普通的存储过程的区别是:触发器是当对某一个表进行操作.诸如:update.insert.dele

  • SQL Server的触发器详解

    目录 什么是触发器 DML触发器分为: 创建触发器 创建insert类型触发器 创建delete类型触发器 创建update类型触发器 update更新列级触发器 instead of类型触发器 创建instead of触发器 显示自定义消息raiserror 修改触发器 启用.禁用触发器 查询创建的触发器信息 示例,验证插入数据 示例,操作日志 总结 触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程.触发器主要是通过事件进行触发被自动调用执行的.而存储过程可以通过存储过程的名称

  • SQL Server Transact-SQL编程详解

    目录 变量 1. 局部变量(Local Variable) 2. 全局变量(Global Variable) 输出语句 逻辑控制语句 1. if-else判断语句 2. while…continue…break循环语句 3. case 4. 其他语句 总结 T-SQL语句用于管理SQL Server数据库引擎实例,创建和管理数据库对象,以及查询.插入.修改和删除数据. 变量 1. 局部变量(Local Variable) 局部变量是用户可以自定义的变量,它的作用范围是仅在程序内部,在程序中通常用

  • Java的内存机制详解

    Java把内存分为两种:一种是栈内存,另一种是堆内存.在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后(比如,在函数A中调用函数B,在函数B中定义变量a,变量a的作用域只是函数B,在函数B运行以后,变量a会自动被销毁.分配给它的内存会被回收),Java会自动释放掉为该变量分配的内存空间,该内存空间可以立即另做他用. 堆内存用来存放由new创建的内存数组,在堆中分配的内存,由Jav

随机推荐