使用即时文件初始化提高SQL Server性能

news/2024/7/5 11:51:54

今天我想谈下SQL Server里的一个特别话题——即时文件初始化(Instant File Initialization)。对于你的SQL Server实例,如果你启用了即时文件初始化,在特定情况下,你会获得巨大的性能提升。即时文件初始化定义了当在数据文件里分配新的空间时,SQL Server引擎如何和Windows操作系统打交道。

问题缘由

在SQL Server默认配置里,当你在数据文件里分配新空间时,SQL Server会调用内部WIN32 API函数,填0初始化新分配的NTFS簇。这就是说新分配的空间的每个字节会用0值(0x0)重写。这个举动会阻止访问到原始数据问题,即在同个NTF簇里物理存储的数据。在下列SQL Server操作中,会发生填0初始化:

  • 创建新的数据库
  • 数据库自动增长
  • 数据库备份还原

当你创建10GB的数据库文件,SQL Server第1步需要把10GB的数据块写上0值。这个会花费很长时间。我们来看下面CREATE DATABASE语句:

复制代码
 1 -- Create a new 10 GB database
 2 CREATE DATABASE TestDatabase ON PRIMARY
 3 ( 
 4     NAME = N'TestDatabase',
 5     FILENAME = N'D:\SQL\DATA\TestDatabase.mdf' , 
 6     SIZE = 10240000KB , 
 7     FILEGROWTH = 1024KB
 8 )
 9 LOG ON 
10 (
11     NAME = N'TestDatabase_log', 
12     FILENAME = N'D:\SQL\Log\TestDatabase_log.ldf' ,
13     SIZE = 1024KB , 
14     FILEGROWTH = 10%
15 )
16 GO
复制代码

从代码可以看到,这里我创建10GB的数据库文件。在我SQL Server默认配置里,这个语句花费了近49秒,因为SQL Server通过WIN32 API函数写入10GB的0到存储。假设你有损坏的数据库(例如也是10GB),你想还原备份,会发生什么?在第1步通常人们会怎么做?是会删除损坏的数据库。这意味这你的数据库文件没了,在还原文件操作期间,SQL Server第1步需要重建文件。

  1. SQL Server第1步创建10GB“空”的数据库,在NTF文件系统里数据文件会被填0初始化。
  2. 最后1步备份被还原时,SQL Server再次写入10GB的数据到数据文件。

你会发现,你写了近20GB的数据到你的存储!如果你在现存的文件上还原你的备份,SQL Server会跳过第1步,直接写入10GB的数据到你的存储——你就获得了100%的性能提升!

即时文件初始化

如果你不想SQL Server进行你数据文件的填0初始化,你可以重新配置SQL Server。如果你授权SERVICE帐号,在对应运行的SQL Server下——执行卷维护任务(Performance Volume Maintenance Task)特权,在你重启SQL Server后,SQL Server会跳过数据文件的填0初始化。我曾说过这只对数据文件有效——在SQL Server里日志文件还是总要填0初始化的!这是米有办法滴!!!如果日志文件没有填0初始化,当日志文件被包裹时,故障还原进程就不知道从哪里结束。故障还原停在它找到下条日志记录需要处理头部0值地方。

你可以通过secpol.msc对SQL Server的SERVICE帐号授予执行卷维护任务(Performance Volume Maintenance Task)特权。

在重启后,SQL Server现在可以跳过数据文件的填0初始化。当我再次执行CREATE DATABASE,它只花费了近210ms——那是巨大的区别!副作用呢?你可以通过DBCC PAGE命令获得在分配的NTFS簇里存储的原始内容: 

复制代码
1 -- Enable DBCC trace flag 3604
2 DBCC TRACEON(3604)
3 GO
4 
5 -- Dump out a page somewhere in the data file
6 -- A hex dump is working here
7 DBCC PAGE (TestDatabase, 1, 1000, 2)
8 GO
复制代码

你看到我在我的数据文件里随便倾倒出了一个页。在那个情况下,SQL Server现在就会返回你一些垃圾数据——在新分配的NTFS簇里先前存储的数据——对SQL Server毫无关联的数据。

通过对SQL Server授予这个权限,基本上你打开了一个安全漏洞:用户(有正确权限的)可以获得老数据,在文件系统里先前存储的。因此对此你必须要仔细考虑下,对SQL Server是否要授予这个特权。

如果你想知道,你的SQL Server是否带这个权限在运行,你可以启用30043605跟踪标记。用这些启用的跟踪标记,SQL Server在错误日志会报告那个文件被填0初始化。接下来当你创建新的数据库时,对于SQL Server没有授予这个特权,从错误日志你可以看到,数据日志文件都被填0初始化了:

如果SQL Server有执行卷维护任务(Performance Volume Maintenance Task)特权,从错误日志你可以看到,只有日志文件被填0初始化:

 

Windows内核

在SQL Server运行下服务帐号,你对它授予了执行卷维护任务(Performance Volume Maintenance Task)特权,在Windows操作系统内部会发生什么呢?启用这个特权后(它内部是通过WIN32 API调用所谓的SE_MANAGE_VOLUME_NAME函数),SQL Server可以调用SetFileValidData的WIN32 API函数。从在线文档里可以看到,调用那个函数的进程,有SE_MANAGE_VOLUME_NAME权限。当那个函数被SQL Server调用时,函数本身会设置文件所谓的High Watermark——在其NTFS簇里,文件直接扩展而不重写原始内容!正如在线文档所述:

 

“The SetFileValidData function allows you to avoid filling data with zeros when writing nonsequentially to a file. The function makes the data in the file valid without writing to the file. As a result, although some performance gain may be realized, existing data on disk from previously existing files can inadvertently become available to unintended readers.”

 

 

“If SetFileValidData is used on a file, the potential performance gain is obtained by not filling the allocated clusters for the file with zeros. Therefore, reading from the file will return whatever the allocated clusters contain, potentially content from other users. This is not necessarily a security issue at this point, because the caller needs to have SE_MANAGE_VOLUME_NAME privilege for SetFileValidData to succeed, and all data on disk can be read by such users.”

 

我已经说过,对于你的SQL Server实例,你是否启用这个权限主要是关系到安全的。

小结

对于你的SQL Server实例,你是否应该启用即时文件初始化?这个依具体情况而定……当你是SQL Server和系统管理员时,授予这个权限是个好主意,因为作为系统管理员,你总是可以访问文件系统的。但当你有专属的系统管理员和SQL Server管理员时,这就不可能授予了,因为系统管理员并不信任你,对于你的SQL Server实例你不会获得这个权限。那样的话SQL Server总会填0初始化数据和日志文件……


本文转自Woodytu博客园博客,原文链接:http://www.cnblogs.com/woodytu/p/4639282.html,如需转载请自行联系原作者


http://www.niftyadmin.cn/n/4072362.html

相关文章

python连接mysql数据表查询表获取数据导入到txt中

import pymysql连接mysql数据表查询表获取数据导入到txt中#查询结果写入数据到txtdef get_loan_number(file_txt): connect pymysql.Connect( host"100.100.100.0", port3306, user"test", passwd"123", …

python基础数据类型之 set 及数据类型补充、编码进阶、小数据池、深浅拷贝

1.集合(set) 集合就是一个没有值的字典,遵循:唯一,无序,元素要求可哈希(不可变) 集合是无序的 集合是可变的 集合的操作方法: 增:s.update("3456") # 迭代添加print(s)s.add("怼怼")print(s) 删:s {1,2,3,"123",False,(1,2,3,4)}print(s)s.pop…

15. Django连接Mysql数据库

安装PyMySQL,打开cmd, pip install PyMySQL在.../blog/init.py 目录下添加:import pymysql pymysql.install_as_MySQLdb() 3.打开settings.py文件,注释粗体部分代码,添加数据库配置代码,如下所示&#xff…

图片的内存缓存控制

为什么80%的码农都做不了架构师?>>> 从网上找到的,自己整理了下: public class MemoryCache{private static final String TAG "MemoryCache";/*** 放入缓存时是个同步操作* LinkedHashMap构造方法的最后一个参数true…

DES算法实例详解

为什么80%的码农都做不了架构师?>>> 译自J. Orlin Grabbe的名作《DES Algorithm Illustrated》,国外许多大学将该文章作为补充材料,可作为理解DES算法的最佳入门手册。反观许多教材介绍DES时直接照搬一张流程图,图中I…

手把手教你如何正确启动Android SDK 1.5模拟器

为什么80%的码农都做不了架构师?>>> 首先要确认下自己的电脑是否安装过JDK、没有的话可以 点我下载(右键迅雷下载) !安装好JDK后,按住键盘上的 WINR 键,在弹出的运行框中输入cmd,回…

《深入java虚拟机》读后(2)

三、OutOfMemoryError 第三章 垃圾收集器与内存分配策略 一、 判断对象是否被实用 1、 引用计数法 给对象添加一个引用计数器,每当有一个地方引用他,计数器就加一,引用失效就减一,计数器为零的对象就是不再被实用的。(…

Tomcat7.0配置

2019独角兽企业重金招聘Python工程师标准>>> Tomcat7.0下载地址:http://tomcat.apache.org/download-70.cgi 选择符合自己操作系统的版本即可(本机win8-64位系统),选择如下: http://118.186.9.91/files/40150000012D8243/123.125.…