先来看看和这个问题相关的Allocation Unit。我们在格式化磁盘的时候, 会有一个选项叫做分配单元大小(Allocation Unit),如下所示:
这个“Allocation Unit(后门简称为AU)”代表什么意思呢?AU 也叫cluster (簇),它代表了一个文件存放在磁盘上的最小分配单位。每个分配单元只能被一个文件使用。文件就是按照这个分配单元的大小被分成若干块存储在磁盘上的。即使文件大小小于这个分配单位,它最小也要占用分配单元大小的磁盘空间。比如一个100 bytes大的文件,当分配单元为512字节时,它占用一个分配单元即512字节的存储空间。如果文件大小为513 字节到1024字节,当分配单元为512字节时,它占用两个分配单元也就是1024字节的存储空间。
我下面图显示所以我的文件test.txt大小是26字节,但是占用空间是4kb。这是因为我磁盘的AU是4kb的缘故
一般来说,似乎分配单元越小越节约空间,分配单元越大越节约读取时间,但浪费空间。但是如果一个文件被分成的块数越多,那么这些块数在磁盘上分散存放的可能就越大(就是碎片),按么读取数据时会浪费一些时间。
上面介绍了Allocation Unit 的概念。这里再介绍另外一个概念,sector,即扇区。磁盘的每一面被分为很多条同心圆磁道,越接近中心,圆就越小。而每一个磁道又按512个字节为单位划分为等分,叫做扇区。扇区大小可能随系统的不同而异。你甚至可以改变扇区的大小。如果不是默认的512字节,需要注意下面的问题
磁盘驱动器在向磁盘读取和写入数据时,要以扇区为单位。连续的sector(扇区)就组成了一个Allocation Unit。
那么如何查看磁盘的AU,sector等信息呢?可以使用fsutil工具。
C:\Windows\system32>fsutil fsinfo ntfsinfo e:输出如下:NTFS 卷序列号 : 0x3c5e6e515e6e03cc版本 : 3.1扇区数量 : 0x00000000061a77ff簇总数 : 0x0000000000c34eff可用簇 : 0x0000000000c2f6bd保留总数 : 0x0000000000000000每个扇区字节数 : 512每个物理扇区字节数 : 512 ß--------sector size每个簇字节数 : 4096ß--------Allocation Unit size每个 FileRecord 段的字节数 : 1024每个 FileRecord 段的簇数 : 0Mft 有效数据长度 : 0x0000000000040000Mft 起始 Lcn : 0x00000000000c0000Mft2 起始 Lcn : 0x0000000000000002Mft 区域起始 : 0x00000000000c0000Mft 区域结尾 : 0x00000000000cc820RM 标识符: 01D0688A-C349-11E2-A1B3-D4BED98EB542
可以看到,我磁盘的扇区大小为512字节,而分配单元为4kb。
有了上面的知识,现在回到我文章头提到的问题。SQL server 日志写(log write)的最小大小是多少呢?为此我做了个试验(Windows 7+SQL server 2012)
1)我把磁盘格式化,最小分配单元为4kb
2)我把log 放到磁盘上
3) 我commit一个非常小的事务
--Create table t1 (c1 int)begin traninsert into t1 values(1)commit
4)我使用Process Monitor 来观察磁盘的读写。看看下图:
我反复试用了多次,我发现SQL server 日志写的最小大小都是512bytes,就是一个扇区的大小。事实上我其实知道,SQL server的日志写就是以扇区大小为单位的。
注意 SQL server的torn page detection和扇区大小密切相关。
注意日志写最小单位512bytes并不意味着总是以这个大小进行写操作。如果事务够大,那么SQL server 会以大于512bytes的大小进行写。比如:
那么最大能够到多大?
让我们试验一下。我使用了下面的脚本,同时开2个窗口运行:
create table t2( c1 int, c2 char(7000))gobegin trandeclare @i integerSEt @i=0while (@i<100000)begininsert into t2 values(@i,'dadf')set @i=@i+1endcheckpointcommitdelete from t2
我发现大部分的日志写都是59kb大小:我发现大部分的日志写都是59kb大小:
但是也有其他的大小,如下面的8MB和4MB:
但是,会不会有比8MB更大的写操作呢?我不知道。
至此,有关磁盘格式化的分配单元问题,答案已经清楚了。SQL server 日志写和扇区大小有关系。SQL server 的日志写的最小单位就是扇区的大小。但是SQL 的每个日志写似乎和磁盘的分配单元无直接关系。尽管如此,我上面试验里面大部分的日志写接近60kb,所以分配单元为64kb似乎比较好些。如果有时间,我下次再写篇文章,做下压力测试,看看分配单元和日志写,或者数据写,究竟有没有性能上的关系。
参考文档:
SQL Server Best Practices Article
http://technet.microsoft.com/en-us/library/cc966412.aspx
http://blogs.msdn.com/b/psssql/archive/2011/01/13/sql-server-new-drives-use-4k-sector-size.aspx
http://support.microsoft.com/kb/926930
文章转载自:
http://blogs.msdn.com/b/apgcdsd/archive/2013/06/17/sql-server-log-write.aspx?CommentPosted=true#commentmessage
文章经作者授权转载,版权归原文作者所有