SQLSERVER 里经常看到的CACHE STORES是神马东东?

当我们在SSMS里执行下面的SQL语句清空SQLSERVER的缓存的时候,我们会在SQL ERRORLOG里看到一些信息

DBCC FREEPROCCACHE

大家可以看到cachestore、object plans、sql plan、bound tress等名词

cachestore flush for the 'Object Plans' cachestore (part of plan cache)

cachestore flush for the 'SQL Plans' cachestore (part of plan cache)

cachestore flush for the 'Bound Trees' cachestore (part of plan cache)

那么这些名词是什么意思呢?是什么功能组件呢?这篇文章为大家介绍SQLSERVER Buffer Pool,大家就会知道了

翻译自:Bufferpool Performance Counters


原文大意

在网上有非常多的文章、博客、帖子介绍内存配置和内存的一些情况,但是依然给大家带来了太多的误解。

这些文章都有讲到SQLSERVER 内存、虚拟内存、AWE功能还有其他的一些介绍我个人认为不能很好地对SQLSERVER内存方面的各个性能计数器有很好的理解

在这篇文章里,我会着重讲解BufferPool的一些机制,例如你的数据页面和索引页面在SQLSERVER的内存里是怎麽存放的

在性能监视器里你能够使用这些知识去判断当前BufferPool的状态。

(当我谈论到页面的时候,我只谈论数据页面和索引页面。对于事务日志记录,有一个特别的日志管理器我将会在

另一篇文章里讲述日志记录是如何写入到日志文件的)

首先让我们来看一下一些Buffer Pool 的一些相关概念。一个简单的Buffer Pool 概念图就像下图那样

POOLS AND CACHE STORES

缓冲池通常会缓存同类的、无状态的数据。所有类型的数据在缓存池中会被视为平等的

例如:连接池或者网络缓冲区

缓冲池的最大作用:拉近了磁盘和CPU的距离,因为数据存放在磁盘,如果经常读取磁盘里的数据会使CPU一直等待,而这个时候缓冲池就将这种距离

拉近了,将磁盘的数据缓存在缓冲池,使性能有极大的提升

Cache stores 通常被用作缓存状态数据和提供一组内存分配接口给不同的客户重用。

例如存储过程缓存会分为几个不同的cache stores

1、第一种用来存储ad-hoc类型SQL 执行计划

2、第二种用来存储存储过程、函数、触发器等的执行计划

3、第三种用来存储扩展存储过程的执行计划

The Free List

SQLSERVER会维护着一个最小数量的空闲页面记录在空闲列表里以能够最快处理传入的请求。

SQLSERVER会尽量在空闲列表里维护着空闲页面的数量(“Min Free“ 在 DBCC MEMORYSTATUS 的输出里面)

的计算是根据 Buffer Pool的大小和传入的请求数(页面平均寿命,在缓存里面页面的寿命就是一个指标)

大家在运行 DBCC MEMORYSTATUS  的时候有没有留意他的输出结果,实际上每一个节就是一个cache store

理解:

cache:缓存

store:店铺

在SQLSERVER Buffer Pool里有很多这样的缓存店铺(cache store),而每家店铺卖的东西是不一样的,更有趣的是每家店铺里

只卖同一样商品

对缓存页面进行写操作和释放操作

SQLSERVER使用LRU-K(Least Recently Used 近期最少使用算法  改进了的LRU算法)去计算在Buffer Pool里的页面寿命

MYSQL和ORACLE也是使用的LRU算法来清除缓存,也对LRU算法进行了改进

基本上,当一个页面每引用一次,计数器就会上升,当lazy writer 进程将页面请出缓存的时候,计数器也会降下来

其他工作线程在特定时刻(例如当一个异步I/O发生的时候)会检查当前Buffer Pool的内存状态确保对新的请求有足够

数量的空闲页面可用。如果空闲的缓存不够,那么会有两件事情发生:

事件一:如果 Buffer Pool的上限已经达到了(这个上限是根据 “max server memory”和当前操作系统的可用内存来的)

这两个都会反映在SQL Server Memory Manager:Target Server Memory 这个计数器)

lazywriter 进程会清除部分 Buffer Pool 缓存

lazywriter 进程清除Buffer Pool 缓存的几种策略:

1、他会跟踪自上次清除缓存时没有被清除的页面,这一次进行清除

2、根据页面最后一次被引用的时间,如果太久没有引用则清除

3、数据页面是否是脏页,如果是脏页面则刷入到磁盘中(dirty page才需要刷入磁盘,修改磁盘上的页面数据,而clean page是不需要刷入磁盘的,因为他在内存里无做任何修改)

清除完毕之后会修改Free List,告诉Free List当前有哪些空闲的页面,如果事务日志记录还没有写入到磁盘,那么脏页是不会被刷入的直到事务日志记录

已经写入磁盘

事件二:如果 Buffer Pool还没有达到上限

那么SQLSERVER提交更多的预留页面( reserved pages 向操作系统申请更多的内存)到Buffer Pool里,而不是像刚才那样,

清除一些页面让这些清除后的页面重新回归到Free List

这就是为什麽Page Life Expectancy 这个计数器在一台瓶颈很小的服务器里会非常高的原因(因为系统还有很多内存)

数据页面不需要被请出 Buffer Pool。

而且Process:Private Bytes (sqlservr.exe) 和SQL Server Memory Manager: Total Server Memory 会一直增长,即使在一台服务器上

活动比较少

刷写数据页面和释放数据页面的三个线程

(一)Lazywriter 线程

Lazywriter 线程是一个系统线程,他会将一批在buffer pool里的脏页刷出并修改buffer pool的Free List

释放buffer pool里的部分页面,将这部分释放的页面的内存返还给操作系统

Lazywriter 线程的主要工作是维护空闲列表 free list

(二)Checkpoint 线程

Checkpoint 线程也是一个系统线程,他会在一定时间里唤醒并检查每个数据库是否超过了Recovery interval

他的主要工作是把脏数据页面刷到磁盘,以便在数据库还原的时候减少事务日志undo和redo的事务数,

然而,Checkpoint 不会去更新Free List

Checkpoint 只是把buffer pool中的脏页面修改到磁盘上的页面上,做完Checkpoint 之后,buffer pool里面的页面还是存在的,没有释放的

(二)Eager Write 线程

Eager Write 线程是一个特别的写机制用作 non-logged 的I/O操作的线程,例如BULK INSERT和SELECT INTO.

这个线程的目的是清除一种叫做Buffer Pool 的无用页面(当发生大容量的数据操作,例如BULK INSERT的时候,

读入到Buffer Pool里的这些数据页面一般不太可能重用),所以当完成大容量操作之后会由Eager Write 线程将这些数据页面进行清除

Eager Write 线程和Lazy writer 线程的区别:

Lazy writer 线程:当操作系统中可用内存不足或者buffer pool已经达到上限 ,而有新请求需要使用数据页面的时候,Lazy writer 线程才会触发,所以叫Lazy

而Lazy writer在清除数据页面的时候,会等事务日志记录flush到磁盘之后才会将数据页面flush到磁盘

在 NUMA系统里面,每一个NUMA节点都会有一个 Lazy Writer线程

Eager Write 线程:做完大容量操作之后,会马上进行数据页面清除工作,所以叫Eager(勤奋)

公式


总结

文章简单介绍了Cache Store的来历和SQLSERVER Buffer Pool的结构,希望对大家理解SQLSERVER Buffer Pool有帮助

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


2014-6-8补充

从SQLSERVER2005开始,使用最新的LRU-K算法清除缓存中的页面

SQLSERVER 里经常看到的CACHE STORES是神马东东?的更多相关文章

  1. SQLSERVER 里SELECT COUNT(1) 和SELECT COUNT(*)哪个性能好?

    SQLSERVER 里SELECT COUNT(1) 和SELECT COUNT(*)哪个性能好? 今天遇到某人在我以前写的一篇文章里问到 如果统计信息没来得及更新的话,那岂不是统计出来的数据时错误的 ...

  2. 用SQLSERVER里的bcp命令或者bulkinsert命令也可以把dat文件导入数据表

    用SQLSERVER里的bcp命令或者bulkinsert命令也可以把dat文件导入数据表 下面的内容的实验环境我是在SQLSERVER2005上面做的 之前在园子里看到两篇文章<C# 读取纯真 ...

  3. 记一次数据库调优过程(IIS发过来SQLSERVER 的FETCH API_CURSOR语句是神马?)

    记一次数据库调优过程(IIS发过来SQLSERVER 的FETCH API_CURSOR语句是神马?) 前几天帮客户优化一个数据库,那个数据库的大小是6G 这麽小的数据库按道理不会有太大的性能问题的, ...

  4. [C++中级进阶]001_C++0x里的完美转发到底是神马?

    [C++中级进阶]001_C++0x里的完美转发到底是神马? 转载至:http://www.cnblogs.com/alephsoul-alephsoul/archive/2013/01/10/285 ...

  5. 在SQLSERVER里,怎么让别人只能输入一个字母的约束该怎么写?就是26个字母中的任意一个?

    alter table 表名 add constraint ck_char check(自段名 like '[a-z]' or 自段名 like '[A-Z]')

  6. SqlServer里DateTime转字符串

    Select CONVERT(varchar(100), GETDATE(), 8):14:53:14 Select CONVERT(varchar(100), GETDATE(), 9): 06  ...

  7. 修改和查询sqlserver里面的xml 好像只能一个个改不能批量

    select [ExtendFieldId], [Setting].value('(/UploadFileViewModel/UploadProviderKey)[1]', 'nvarchar(max ...

  8. SQLServer 里面的 DDL,DML,DCL,TCL(转)

    1.DDL (Data Definition Language )数据库定义语言 statements are used to define the database structure or sch ...

  9. SQLServer 里面的 DDL,DML,DCL,TCL

    1.DDL (Data Definition Language )数据库定义语言 statements are used to define the database structure or sch ...

随机推荐

  1. js获取浏览器语言(ie、ff、chrome)、contextpath

    /js获取浏览器语言(ie.ff.chrome) var language_en_us = "en-us"; var language_zh_cn = "zh-cn&qu ...

  2. Android开发者必须掌握的知识技能清单

    1.Android平台原理机制.客户端性能优化.软件架构设计,熟悉Android应用开发框架,能独立开发高性能的Android应用 2.同步.异步.多线程.跨进程,数据结构和计算机系统和NDK即c++ ...

  3. 【转】常用css命名规则

    常用的css命名规则 头:header 内容:content/container 尾:footer 导航:nav 侧栏:sidebar 栏目:column 页面外围控制整体布局宽度:wrapper 左 ...

  4. sql server 行转列解决方案

    主要应用case语句来解决行转列的问题 行转列问题主要分为两类 1)简单的行转列问题: 示例表: id  sid           course  result 1   2005001 语文     ...

  5. bind的用处

    刚做的项目,遇到过这样的问题,就是在动态追加标签时,给追加的标签添加事件时,在标签内追加不了,后来使用了delegate代理,能响应了,但也是不能给动态追加的代理 $("body" ...

  6. ubuntu 14 配置 tomcat

    参考 http://www.linuxidc.com/Linux/2015-01/111119.htm

  7. Style file: generic.xaml

    All silverlight control style should be designed in generic.xaml which is in theme folder. But when ...

  8. 51单片机ALE引脚的控制(摘录)

    ALE/PROG: 当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节. 在FLASH编程期间,此引脚用于输入编程脉冲. 在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频 ...

  9. php 下载图片 文件

    $file = dirname(dirname(__FILE__)) . $_GET['download']; //获取图片的绝对路径 header("Content-type: octet ...

  10. Python全栈之路6--正则表达式

    正则本身就是一门语言: 正则表达式使用单个字符串来描述.匹配一系列符合某个句法规则的字符串,在文本处理方面功能非常强大,也经常用作爬虫,来爬取特定内容,Python本身不支持正则,但是通过导入re模块 ...