15

SQLServer:页及区的状态和分配

有三个缩写词:GAM,SGAM,PFS。
GAM(全局分配映射表),GAM页记录已分配的区,每个GAM包含64,000个区,相当于404GB的数据。GAM用一个位来表示所涵盖区间内的每个区的状态,如果位为1,则区可用,否则已分配。
SGAM(共享全局分配映射表),同GAM一样,不过SGAM是用来监控混合区的,如果至少有一个页未有,则标志位为1,否则所有页都在使用中。
FPS(页可用空间),记录每页的分配状态,是否已分配单个页以及每页的可用空间量。PFS 对每页都有一个字节,记录该页是否已分配。如果已分配,则记录该页是为空、已满 1% 到 50%、已满 51% 到 80%、已满 81% 到 95% 还是已满 96% 到 100%。

将区分配给对象后,数据库引擎将使用 PFS 页来记录区中的哪些页已分配或哪些页可用。数据库引擎必须分配新页时,将使用此信息。保留的页中的可用空间量仅用于堆和 Text/Image 页。数据库引擎必须找到一个具有可用空间的页来保存新插入的行时,使用此信息。索引不要求跟踪页的可用空间,因为插入新行的点是由索引键值设置的

在数据文件中,PFS 页是文件头页之后的第一页(页码为 1)。接着是 GAM 页(页码为 2),然后是 SGAM 页(页码为 3)。第一个 PFS 页之后是一个大小大约为 8,000 页的 PFS 页。在第 2 页的第一个 GAM 页之后还有另一个 GAM 页(包含 64,000 个区),在第 3 页的第一个 SGAM 页之后也有另一个 SGAM 页(包含 64,000 个区)。下图显示了数据库引擎用来分配和管理区的页顺序。

 

归类于:数据库 标签:SQLServer 页及区的状态
14

SQL Server 页和区(Pages and Extents)

 页是SQL Server数据存储的最基本单位,数据文件(.mdf或.ndf)分配的磁盘空间可以从逻辑上划分成页(从0到n连续编号). 磁盘I/O操作在页级执行,区是八个物理上连续的页的集合,用来有效地管理页,所以页都存储在区中。日志文件不包含页,而是一系列日志记录。
 
页的大小是8KB,这意味着SQL Server数据库中每MB有128页,16个区。
 
关于页
每页的开头是96字节的标头,用于存储有关页的系统信息,此信息包括页码、页类型、页的可用空间以及拥有该页的对象的分配单元ID。
在数据页上,数据行紧接着标头按顺序放置。页的末尾是行偏移表,对于页中的每一行,每个行偏移表都包含一个条目。每个条目记录对应行的第一个字节也页首的距离,行偏移表中的条目的顺序与页中行的顺序相反。
 
行不能跨页(页的单个行最大数量是8,060字节8kb 1024*8),不包括Text/Image类型的页数据,对于可变长类型的列,如果行超过8060,则从最大长度的列开始,将一个或多个可变长度列移动到ROW_OVERFLOW_DATA分配单元中的页,在原始页上维护一个24字节的指针,如果行的总大小小于8060,就再移回来.执行查询等操作时将延长处理时间,因为这些记录将同步处理,而不是异步。
 
关于区
SQL Server有两种类型的区:
统一区:由单个对象所有,区中的所有8页只能由所属对象使用
混合区,最对由八个对象共享,区中8页可由不同的对象所有。
通常从混合区向新表或索引分配页。当表或索引增长到 8 页时,将变成使用统一区进行后续分配。如果对现有表创建索引,并且该表包含的行足以在索引中生成 8 页,则对该索引的所有分配都使用统一区进行。
归类于:数据库 标签:SQLServer 页和区 Pages Extents
13

SQL Server 文件及文件组

 SQL Server 将数据库映射为一组操作系统文件,每个数据库至少包含一个数据文件和一个日志文件,每个数据库至少有一个主要文件组(PRIMARY),文件组的作用是用于将数据文件集合起来,以便于数据分配和管理。
 
SQL Server数据库有三种类型文件,默认扩展名为:.mdf,.ndf,.ldf. ,允许使用自定义扩展名。
主数据文件(.mdf) 是数据库的起点,指向数据库中的其他文件,每个数据库都有且仅有一个主数据库文件。
次要数据文件(.ndf) 除主数据文件以外的所有数据文件都是次要数据文件,使用次要文件可以将数据分配到不同的磁盘驱动器上来提高性能。
日志文件(.ldf) 每个数据库必须至少有一个日志文件,默认情况下,数据和日志文件被放在同一驱动器的同一路径下,建议将数据和日志文件放在不同的磁盘上。
 
相关T-SQL:
创建文件组
ALTER DATABASE dbname ADD FILEGROUP fgname (注意没有单引号,下同)
删除文件组
ALTER DATABASE dbname REMOVE FILEGROUP fgname (文件组必须为空)
添加文件到文件组
ALTER DATABASE dbname
ADD FILE ( NAME = N'logical_filename', FILENAME = N'ph_filename' , SIZE = 3072KB , FILEGROWTH = 1024KB ) 
TO FILEGROUP fgname
删除文件
ALTER DATABASE dbname  REMOVE FILE logical_filename
在文件组上创建表
CREATE TABLE tname
(
  cola int PRIMARY KEY,
) ON fgname
 
修改默认文件组
ALERT DATABASE dbname
MODIFY FILEGROUP fgname DEFAULT;
 
归类于:数据库 标签:SQLServer 文件文件组
11

茶乡

 过年回家带过来的茶叶都喝完了,虽然对茶没太多研究,但没茶喝,这日子过起来还真感觉少了点什么,中午吃完饭溜了二里路去附近的张一元买了斤信阳毛尖,虽然没了国家,但还是有家乡的,这么多年在外边,除了朋友送的茶,基本上只喝信阳毛尖,渐渐的也就成了一种习惯。
 
有茶喝,日子就感觉到有滋味多了,今天也没啥事,整杯茶,看大壮玩游戏被虐,然后再敲几行代码,翻几页书,下午就打发过去了。
 
归类于:生活芝门 标签:茶乡
11

他们的国家

 我:为什么我在自己的国家都过的这么郁闷,看阉割版的电影,上阉割版的互联网,玩阉割版的游戏,看太监版的电视,是不是接下来要阉割自己了?
大壮:错,这是他们的国家,还有,你早已被阉过了。
 
归类于:生活芝门 标签:他们的国家
08

激情7月

七月八号了,
今年过一半了,
状态越来越好了,
早上能按点上班了,
每天都能吃上早饭了,
吃完早饭能爬上八楼了,
见到同事也敢说早上好了,
敲起代码来也觉得有意思了,
头脑清醒上班不再想打瞌睡了,
每天能看会书开始吸收新知识了,
愿意出去玩玩不窝在家里做宅男了,
于是又开始策划如何成就我的人生了,
天天这般吃得好睡得香体重还能减减了,
生活如此美好,不觉又要TMD的去上班鸟。
 
归类于:生活芝门 标签:激情
26

实现批量数据迁移的托管级代码解决方案 - SqlBulkCopy

SqlBulkCopy是.Net2.0之后就提供的一个类,经实测能实现W/S的写入速度,应该算是挺高效的,不亚于SQL Server的命令行工具 bcp,但如果你的数据源和目标表在同一个SQL Server 实例中,建议你使用T-SQL语句INSERT ... SELECT来完成数据复制工作。

SqlBulkCopy的具体使用方法,我就不介绍了,不喜欢贴代码,反正非常简单,参考MSDN即可,支持的写入数据源是DataRow ,DataTable ,IDataReader ,所以只要是能生成上面这几种数据对象的数据源都可以。

写几条注意事项吧:
1. SqlBulkCopy的类定义是:publie sealed class SqlBulkCopy : IDisposable ,所以用的时候别忘了using或最后调用dispose.
2. 如果数据源和目标表的字段顺序不一致或少于目标表的字段数,必须要设置ColumnMappings,即使字段名称一样也不行。
3.如果需要时间较长,请设置BulkCopyTimeout,单位秒,默认是30秒,设置连接串上的Timeout对此无效。
4.如果想实时了解复制进度,可以订阅SqlRowsCopied事件,并设置NotifyAfter属性,NotifyAfter属性指定完成多少行通知一次。
5.支持事务,一种是SqlBulkCopy内部事务,通过在构造的时候指定SqlBulkCopyOptions.UseInternalTransaction选项即可,这个每完成一个Batch就会提交,失败的Batch不会影响已提交的。另一种就是连接级的事务,影响所有批次
6.设定BatchSize指定每批次提交行数,不设置默认为一次性提交
7.通过在构造函数中设置:SqlBulkCopyOptions.KeepIdentity ,可以保证Identity列值不变。同时设置多个选项,使用 | 运算符。
8.目标表仅限于 SQL Server tables.
 
归类于:数据库 标签:SqlBulkCopy 大数据批量迁移
23

生活挺有意思的,感谢互联网

今天把签名换成了这个标题,周末没怎么上网,所以早上上网看看了看最近发生的几件事,一个是CCAV教大家怎么选择关键词来搜索需要的信息,然后就是石首市的事件。

网上帖子说CCAV请的专家用boobs这个词在google浏览器中搜索,并将搜索结果通过google翻译转换成中文,于是乎,找到了想要找的东西,技艺之高超真是我等闲之辈所能了解的。
这个专家给我们的友情提示是:要想找到你想要的东西,不能使用中文关键词搜索,你至少要掌握一门外语,所以青少年们努力学习外语吧!
而CCAV给我们的友情提示是:你想搜索到你想要的东西,你不能用国内的搜索引擎,你必须用google啊,只有google能找的着,毕竟国内的是的intranet搜索,特别是某熊掌牌搜索引擎,搜索结果前三名基本上都来自于自家。
谢谢专家!谢谢CCAV!

石首市那件事我也不知道后来怎么样了,法医正在鉴定,希望不用等太久能看到大结局。
 
周五的时候和帅哥说年龄大了,当不了愤青了,只能当观众,结果今天就发现当观众的好处,这角色一换,生活立刻感觉有意思多了,终于对“人生如戏”这句话有了点领悟,之前可能也就停留在字面意思理解上。

生活真TMD的有趣,感谢互联网,能免费看大片,睡醒了接着看!
 
-------------------------------
Update 2009.6.25
石首一案结论是自杀,但家属可获赔22万元,石首市吸毒现象严重,不知道还有后续不。
 
归类于:生活芝门 标签:人生如戏
22

ASP.NET 页面指令 之 @OutputCache

缓存的重要性就不用再强调了,@OutputCache给我们提供了一种声明的方式(对应的还有编程的方式)来控制页面和用户控件的缓存策略,这是一种最简单直接的网站优化方式。

还是先来过一遍@OutpuCache所有的属性,共用11个属性,这个指令可以用于页面(.aspx)和用户控件(.ascx)
属性
Duration
页或用户控件进行缓存的时间,单位秒,可以在页面或控件上设置该属性来建立一个缓存的过期策略,该属性是必须的。
VaryByParam
分号分割的字符串列表,是否根据某个参数变化,和VaryByControl二者必须有一。如果不变化,可将值设置为none,否则设置为*,或者变化的参数名称(Get或Post的参数)。
VaryByControl
分号分割的字符串列表,只限于用户控件,串列表的值是服务器控件标识。
Location 缓存的位置,默认是Any,该属性仅限于.aspx文件,可选项是Any,Client,Downstream,Server,None,ServerAndClient
Shared 该属性仅限于.ascx文件,默认为false,用户控件是否可以由多个页面共享。
CacheProfile 你可以在web.config中配置一个缓存设置,这样以后就可以共用这个缓存设置,方便统一修改,不支持用户控件
NoStore 这个不是太清楚什么用,MSDN上说是决定是否对敏感信息辅助存储.
VaryByContentEncodings 同样也是逗号分隔的字符串列表,根据Accept-Encodeing Http头来决定是否缓存不同的版本。
VaryByHeader 根据Http headers来决定是否进行分版本存储,同样也是分号分隔的字符串列表
VaryByCustom 通过这个属性,你可以自定义怎么来缓存页面
SqlDependency 为当前缓存指定一个依赖项,当发生变动时从缓存区中删除掉当前页面或控件的缓存。
 
就是上面列的着11个属性,大多数时候,只需要DurationVaryByParam这两个属性就搞定了,比如:

<%@ OutputCache Duration="100" VaryByParam="none" %>

上面指令没有指定Location默认是客户端和服务器端都缓存,这个时候如果改变页面的QueryString会被忽略,直接从缓存中返回结果,所以在需要根据参数返回不同内容的页面千万不要这么设置,可以采用以下方式:

<%@ OutputCache Duration="100" VaryByParam="*"%>

上面关于Duration属性,说是必须的,其实也不然,当你不想用缓存是就不必写^_^,如下,禁用当前页面缓存:
<%@ OutputCache Location="None" %>
 
归类于:代码人生 标签:@OutputCache ASPNET Directive
03

ASP.NET: 页面指令 之 @PreviousPageType

接着上回的继续写,这个指令到目前为止没用过,有两个二选一的属性,主要的功能是为当前的页面指定一个强类型的PreviousPage.
 
@PreviousPageType属性(Attributes)
TypeName:指定前置页面的类型名称。
VirtualPath:指定前置页面的虚拟路径。
这两个属性不能同时出现,否则就白填,指令无效。
 
大多数时候应该都用不到这个指令,因为当前页面的PreviousPage的值并不取决于这个指令,而是你调用这个页面的方式,只有跨页面的提交和在服务器端调用Transfer时才会保存前置页面的实例.Page类提供IsPostBack,IsCallback,IsCrossPagePostBack三个属性来判断用户是如何来判断当前页面是如何被调用的。
 
Page.PreviousPage这个属性到目前我也没用过,好像很少需要获取前一个页面的对象实例,大多数情况下,页面间的数据传递都是通过QueryString、Form、Cookie等方式完成了。
 
随着Ajax的不断流行,现在连Server Control用的都少了,可惜MS花了这么大精力构造的WebForm框架.
归类于:代码人生 标签:ASPNET @PreviousPageType