图片 8

读书笔记,内存初探

一. 前言

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

配置SQL Server去使用 Windows的 Large-Page/Huge-Page  allocations

目录表->页表->物理内存页

 

看这篇文章之前可以先看一下下面这篇文章

虚拟内存,物理内存,页面文件,还有任务管理器一些概念的解释

了解一下虚拟地址空间(VirtualAddressSpace,VAS)的概念

 

 

前几天在论坛里遇到一个问题

问题地址:

其中提到一个可能性的原因,开启了Large-Page
allocations,看完文章之后就会知道,其实跟Large-Page
allocations无多大关系

Large-Page
allocations
是什么来头??

参考这篇文章:Configuring SQL Server to use Windows Large-Page
allocations

 

今天,一个可改变控制的实现激使我去写这篇文章,这个可改变的控制就是允许运行在Windows200864位服务器上的SQL
Server 2005企业版上

使用跟踪标志834,SQLSERVER会利用 Large-Page
allocations去构建内存中的Buffer Pool。

下面是我对 Large-Page allocations的理解和这个Large-Page
allocations对性能的提升


页面分配

虚拟地址空间(VirtualAddressSpace,VAS)由很多的内存页面组成。这些页面有两种大小,32位系统是小的页面只有4KB大小(IA64位系统上是8KB)

64位系统上是大的页面有2MB大小(IA64位系统上是16MB)。

虚拟地址空间(VirtualAddressSpace,VAS)是由页面描述符表(简称页表)这种结构来维护的,因此,每个虚拟地址空间在页面描述符表里都有对应页面表入口

(个人感觉类似于系统服务描述符表SSDT
,内核描述符表GDT/LDT)。硬件利用这个表将这些入口转译出可读的格式,无论什么时候转译一个虚拟地址,

都必须去这张表找虚拟地址的入口。为了加快查找表上这些入口的速度,CPU维护了一块缓存叫做:Translation
Look-Aside Buffer (TLB)

TLB的工作方式类似于SQLSERVER的执行计划缓存,只要一个入口曾经被转译过下次就不需要再次转译,大页的好处是提高TLB命中率,减少内核cpu消耗。

 

知道这个,就很容易去理解大的页面和小的页面对性能的差别。当一个进程的虚拟地址空间(VirtualAddressSpace,VAS)(每个进程只有一个虚拟地址空间,

虚拟地址空间=一个进程使用的内存)是由小的内存页面构成的,那么在页面描述符表里的入口就需要相应增加,同时TLB缓存的入口数也会相应增加。

举个例子,有几个虚拟地址空间需要被缓存,使用小页面(一个页面4KB)就需要在TLB中缓存更多的入口。更多的入口意味着无论什么时候接收到

一个新的转译请求,TLB的入口缓存就需要更多去循环利用。因此使用大页面去分配虚拟地址空间在性能上会有一定的提升。

图片 1

 

大的页面2MB大小,小的页面4KB大小,比如一个进程需要8MB内存,那么需要4个大页面或者2000个小页面

所以使用小页面来分配虚拟地址空间,就需要在TLB缓存更多的入口,但是TLB缓存的大小是有限的!!

 

 

页面分配和SQLSERVER

就像我早前提到过的跟踪标志834,834跟踪标志会强迫SQLSERVER进程虚拟地址空间使用大页面去构建Buffer
Pool。这个跟踪标志

只能在64位SQLSERVER企业版,并且需要开启 Lock Pages in
Memory
功能才能使用。

当SQLSERVER使用大页面分配的时候,在SQL服务启动时入口信息会被记录在SQL
ERRORLOG里

Large Page Extensions enabled.
Large Page Granularity: 2097152
Large Page Allocated: 32MB
Using large pages for buffer pool.
10208 MB of large page memory allocated.

如果SQLSERVER帐户没有Lock Pages in Memory的权限,就会在SQL
ERRORLOG里记录下错误信息

Cannot use Large Page Extensions: lock memory privilege was not
granted.

这篇文章非常友好地阐述了大页面分配和阐述了需要使用跟踪标志834
并使用64位SQLSERVER企业版才能使用大页面分配


 

注意:(1)不能在SQLSERVER运行的过程当中指定跟踪标志834

DBCC TRACEON(834,-1)

正在忽略跟踪标志 834。该跟踪标志无效,或者只能在服务器启动过程中指定。
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

只能在SQLSERVER启动的时候加上启动参数:834

 

(2)如果SQLSERVER的《max server
memory》选项被设置为0,当SQLSERVER启动的时候会占用整个服务器的所有物理内存

(3)服务器需要有8GB或以上的物理内存操作系统并且必须是企业版才能使用大页面分配

(4)可以使用下面SQL语句查看当前大页面分配的内存

SELECT  large_page_allocations_kb ,
        locked_page_allocations_kb
FROM    sys.dm_os_process_memory

图片 2

(5)如果系统符合大页面分配,并且开启了834跟踪标志,那么当SQLSERVER启动的时候会比较慢,可能需要几分钟时间

2009-06-04 14:20:31.14 Server      Large Page Allocated: 32MB 
2009-06-04 14:20:40.03
Server      Using large pages for buffer pool. 
2009-06-04 14:27:56.98
Server      2048 MB of large page memory allocated.

上面的时间显示SQLSERVER用了7分钟时间来分配页面

 

 

总结:

为什麽SQLSERVER启动的时候就占用了服务器的所有内存,其中的一个原因有可能是你开启了跟踪标志834符合SQLSERVER使用大页面分配虚拟地址空间的要求,并且设置《max
server memory》选项为0

 

 

相关文章

SQL Server and Large Pages
Explained….

 

如有不对的地方,欢迎大家拍砖o(∩_∩)o 

 

2014-5-25补充

SQLSERVER2012新的内存管理器支持分配所有的大小。single page
allocator和multi-page allocator都将退出历史舞台

不论分配多大的内存大小,内存管理器都只有三种不同的内存模型:

1、普通页

2、锁定页(locked
pages,意思即是说通过设置组策略锁定内存页功能,把页面锁定在内存)

3、大内存页(large pages)

 

上面3种页面在SQLSERVER启动的时候ERROR
LOG里都会打印出来,当前使用的是哪种模式的内存

 

大内存页的使用只存在于64位版的SQL Server中

1、新的内存管理器是完全支持NUMA的

2、虚拟地址空间的管理是完全动态的,特别是对32位的实例也是如此

3、内存管理器分配出去的内存都受max server memory控制

4、32位实例不再支持AWE

32位的SQLSERVER2012只能使用4GB物理内存,如果你需要使用更多的物理内存,必须要升级到64位版本

图片 3

 

实际上,跑在Linux上的Oracle也有这个问题,在Linux上开启huge page/large
page的方法

1、/etc/sysctl.cnf 中增加vm.nr_hugepages参数来为大页设定一个合理的值,值的单位为2MB,需要重启Linux

2、echo 一个值到/proc/sys/vm/nr_hugepages中也可以临时性的对大页进行设定

具体参考:

 

 

 

本文版权归作者所有,未经作者同意不得转载。

自调整的数据库引擎(Self-tuning Database Engine)

二. 内存和硬盘

         为什么内存是宝贵的,在每个系统上都是有限的,就像你看到的1
tb的硬盘,但是你通常看到的是50-200 G的内存,
物理内存的访问速度非常快,不能超过一定的限制。在内存有限的情况下,如果所有的进程都使用了有限的内存,并且新的进程将无法为他们找到任何内存,这就出现了虚拟地址空间的概念(也称为VAS)。

长期以来,微软都致力于自调整(Self-Tuning)的SQL
Server数据库引擎,用以降低产品的总拥有成本。从SQL Server 2005开始,SQL
Server就是动态管理内存使用,并且调整内存使用时,不需要重启数据库引擎。

  Virtual Address Space(虚拟地址空间)

    是指一个应用程序能够申请访问的最大地址空间。32位寻址空间最大是4G, 
 64位寻址空间最大是8TB。

    VAS作为中间的抽象层的,
 不是所有的请求都直接映射到物理内存,它首先映射到VAS然后映射到物理内存。因此,它可以更协调的方式管理对内存的请求,而不是让进程去做,如果不是这样,它很快就会导致内存崩溃。

    在Windows操作系统中,VAS
的内核进程与用户进程之间的划分是相同的。对于32位系统,最大的VAS 是4
G的内核/ 2 G到应用程序的中,在这里,SQL
Server是应用程序进程,当我使用word进程时,它意味SQL
Server进程差不多一样,将得到2
G的VAS。因此,从理论上讲,这意味着任何应用程序进程在32位上运行的都将拥有最大限度的2
G。

所以它也不提供内存分配的微调项。各个组件的内存分配,完全由数据库引擎自动管理,不能手动分配。但是这货还是提供了一些配置项,能够影响数据库引擎如何使用内存。

三 sql server 内存 架构

             sql server 内存管理,在sql server
2012发生了重大改变,对内存重新实现了一遍。
 先看下版本之间内存管理图的区别

           
  图片 4图片 5

是否使用这些配置项来替代默认值,取决于操作系统版本,SQL
Server版本,可用物理内存和处理器架构等。

    名词术语 

 

   3.1 BufferPool      

    SQL Server使用BufferPool缓冲池来有效地管理SQL
Server进程的内存请求。它是SQL
Server的最大内存消耗者。缓冲区是内存中的一个8
KB的页面,与数据或索引页面大小相同,您可以将缓冲区看作是一个框架,它在从磁盘到内存的时候保存数据和索引页。

    SQL
Server缓冲区管理器管理将数据页读入缓冲池的任务,并将其写入磁盘。它是SQL
Server的预留内存存储,如果您不为它设置值,它将占用尽可能多的内存。因此,在spconfigure中为max
server内存设置最佳值总是被推荐为一种良好的实践。缓冲池只将内存分配给需要少于8
KB页面的请求。

    对于大于8 KB内存的所有请求,都是由windows
API直接分配的。所有缓存存储计划、数据和索引页都存储在这个缓冲池中。当用户请求row/rows时,如果缓冲区池中没有,则使该页面从磁盘进入内存。这种输入/输出可能在繁忙的系统上特别昂贵,因此尽可能减少SQL服务器缓存的大小,这可能会被用户看作是内存泄漏或SQL
Server占用大量内存,但实际上它提高了性能,实际上这个特性是通过设计实现的。

    下面这些内存不是来自缓冲池:
      SQL LCR
      扩展存储过程
      链接服务器分配的内存
      内存管理器完成的大页面分配(大页面为任意页面>8 KB)
      COM对象

SQL Server是怎么分配内存的

         3.2   single-page 

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

SQL
Server本身设计就会尽可能多的使用内存。正常情况下,它不会释放已经分配的内存,除非OS引发并设定Low
Memory资源通知标记(Resource Notification Flag)。

         3.3 multi- page

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

SQL Server
2005的SQLOS中添加了一个专用线程用于监控OS发出的内存通知(Memory
Notification)(这也是自调整功能之一)。

      3.4  any size page

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

OS中有两种类型的内存通知:

  四. sql server 2008 内存

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

Memory High:SQL Server可以增加Working Set使用量并使用更多内存

        内存的分类方式有很多,下面介绍三种方式:

Memory Low:OS有内存压力,SQL Server释放一些内存给OS

  1. 按用途分类 

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

                          当用户修改了某个页面上的数据时,sql
server会在页存中将这个页修改。但不会立刻将这个页面写回硬盘,而是等后面的checkpoint
或lazy write集中处理。

                 1.2 各类Consumer功能组件

                            Connection 连接:包括输入缓冲池和输出缓冲池,
用来存储用户指令和返回结果。

                            General :一组大杂烩:
语句,语句编译,范式化,锁数据结构,事务上下文,表格,索引的元数据等。

                            Query paln:语句和存储过程的执行计划。

                            Optimizer:sql
server在生成执行计划的过程中需要消耗的内存。

                            Utilities:像BCP, Log Manager,Parallel
Queries,Backup

                 1.3    线程内存

                             为每个线程分配0.5MB的内存

                 1.4    第三方代码申请的内存

        如用户定义的CLR,Linked
Server分布式查询从远程数据库取回大量数据。

如果两种内存通知OS都没设定,则表明内存使用稳定,SQL
Server将继续在现有的进程空间内运行。但是这个功能在Windows 2003和SQL
Server 2005之前是没有的。

  2. 按申请方式分类

    
 申请方式是指要先预先Reserve一块大的内存,然后再一小块一小块的commit。对Database
Cache是会先Reserve,再commit。

    其他所有内存使用,基本都是直接commit,都叫Stolen。

内存压力分类,根据Memory Pressure –
Classified:

  3. 按申请大小分类(上面的内存图就是这种分类)

    有二种内存申请单位:  一种是小于或等于8KB的,称为Buffer
Pool,一次一个页面的这种分配,被称为single page allocation.

    
 一种是大于8kb的,称为Multi-page(以前叫MemToLeave),这种分配,被称为
Multiple Page Allocation.

    注意这里的很大一部分内存不受 sql
server本身控制.因为第三方代码申请的内存都放在Multi-page里.

  
图片 6

  内存分类方法之间的关系

类型

Database cache

数据页面缓冲区

Consumer

功能组件

3 Party code

第三方代码

Threads

线程

Reserved/Commit

一般不是

一般不是

不是

Stolen

不是

Buffer Pool

(single- page)

所有

绝大部分

没有

没有

MemToLeave

(Multi -page)

没有

一小部分

所有

所有

 

SQL Server可以使用多少内存,取决于:

五.sql server 2012 内存

   在 sql server 2012里,single page  allocator 和multi page
allocator 统一起来了,叫做any size page allocator。max server memory
不再像以前的版本那样,只控制buffer pool的大小,也包括那些大于8kb
的内存请求。也就是max server memory 能够更准确地控制SQL Server
的内存使用了。

  如下图所示:

    图片 7

         使用dmv 来查看当前实例的总内存空间,以及占用内存空间

    –Target Server Memory (KB)最多能申请的内存量
    –Total Server Memory (KB) 目前使用了多少内存量

         从下面的空间占用也可以看出来, 给sql server有分配多少内存,
它就会占用多少内存,以达到性能的最优。

select counter_name, ltrim(cntr_value*1.0/1024.0/1024.0)+'G' 
as memoryGB from master.sys.dm_os_performance_counters  
where counter_name like '%target%server%memory%'or  counter_name like '%total%memory%'

     
  图片 8

  • 服务器上安装的内存量
  • Windows系统的内存限制
  • SQL Server的架构(32bit/64bit)
  • SQL Server控制内存使用的配置项
  • SQL Server的版本

 六  总结

  当您启动Microsoft SQL Server时,SQL
Server内存使用量可能会继续稳步增长,而不是减少,即使服务器上的活动很低。此外,任务管理器和性能监视器可能显示,计算机上可用的物理内存会逐渐减少,直到可用内存在4
MB到10 MB之间。这种行为本身并不表示内存泄漏。这种行为是典型的,并且是SQL
Server缓冲池的预期行为。

  默认情况下,SQL
Server根据操作系统报告的物理内存负载动态地增长和缩小缓冲池(缓存)的大小。只要有足够的内存(4
MB和10 MB)可以防止分页,那么SQL Server缓冲池就会继续增长。当与SQL
Server在同一台计算机上分配内存时,SQL
Server缓冲管理器将根据需要释放内存。SQL
Server可以每秒释放数兆字节的内存。这允许SQL
Server快速地适应内存分配更改。

   您可以为SQL
Server数据库引擎使用最小服务器内存和最大服务器内存配置选项使用多少内存(缓冲池)设置上限和下限

  请注意,通过上图设置内存最大 max 只限制SQL
Server缓冲池的大小。不限制SQL
Server为其他组件分配的剩余未保留内存区域,如扩展存储过程、COM对象、非共享dll、EXEs和MAPI组件。由于之前的分配,SQL
Server私有字节的数量超过了最大服务器内存配置。 

        后面章节在详细介绍内存的查看分析

 

参考文献:

  SQL Server Memory and Troubleshooting

      Microsoft SQL Server企业级平台管理实践

      SQL Server 2012 内存管理 (memory management)
改进

 

 

32位VAS的限制 

Windows在VAS中运行每一个进程。32位的进程最多只可寻址到4GB内存,而这4GB内存又分为内核模式(Kernel
Mode)空间和用户模式(User Mode)空间。默认,windows会各分配2GB。

内核模式主要用于OS,用户模式用于当前执行的应用程序进程(例如SQL Server)。

  1. 用户模式VAS分配和VirtualAlloc

      SQL
Server保留的2GB用户模式VAS,当出现物理内存分配时才会提交。它是通过VirtualAlloc这个Windows
API。

      32位的SQL
Server或者Windows,调用VirtualAlloc返回一个32位的指针,这就是为什么SQL
Server只能使用到2GB用户模式VAS的原因。

     
通过VirtualAlloc分配的内存并不一定是实际物理内存,当分配的内存被提交时,才会是RAM的内存。提交内存时,windows要确认SQL
Server及其它应用程序进程提交的内存总量<=(RAM+分页文件)。

     
需要注意是VirtualAlloc分配的内存是可分页内存,意味着OS出现内存压力时,它们会被分页(page
out)到磁盘上。

  2. 非缓存池分配(MemToLeave)

     SQL
Server占用的大部分内存分配给了缓存池,用于缓存数据和查询计划。当需要大于8KB的连续页时,会通过多页分配器分配非缓存池,如LinkedServer,线程堆栈,CLR,备份缓存等。

     为了确保有足够的非缓存池内存,32位SQL
Server在启动时就会保留部分VAS。保留的部分也叫做MemToLeave,大小=MaxWorkerThread*0.5MB+256,其中MaxWorkerThread=(ProcessorCount-4)+256.

    
默认情况下MemToLeave=256*0.5+256=384MB,所以缓存区的大小约为(2GB-384MB)=1664MB。

  3. VAS调整(VAS Tuning)

   
在有4GB内存的服务器上,可以使用VAS调整使得用户模式VAS占到3GB,内核模式VAS减少为1GB.

    需要注意的是内核模式内存的减少,使得系统PTEs(Page Table
Entires)减少,造成系统不稳定,同时SQL Server可以寻址到的内存也变少了。

    Windows 2008上实现VAS Tuning,使用BCDEdit /set IncreaseUserVa
[value](value取2048到3072间的值)。

  4. AWE(Address windowing extension)

    在多于4GB RAM的服务器上,可以使用AWE让SQL
Server使用内存。使用AWE需先启用PAE,在windows 2008上使用BCDEdit /set PAE
ForceEnable启用。

    然后SQL Server开启”AWE
Enabled”,服务账号需要具有锁定内存页的权限(Lock Pages In
Memory,在组策略分配这个用户权限)。

   
AWE使内存管理的指针由32扩展到36位,所以最能寻址64GB内存。并且分配内存时,不使用VirtualAlloc而使用AllocateUserPhysicalPages函数。此API通过PTE直接分配物理内存。

    AWE的内存只能被缓冲池(Buffer
Pool)使用,并且是被锁定和不可分页的,所以最好使用设定“’max server
memory”来限制一下量。

  5. -g启动参数

    32位平台上可以使用SQL
Server的-g启动参数指定MemToLeave内存量,从而提高MemToLeave的内存分配量。但同时这也会减少缓存池的分配量。

 

使用64位的SQL Server

发表评论

电子邮件地址不会被公开。 必填项已用*标注