第4周 页面限制8060 bytes

恭喜您!在你面前就只剩下几页了,然后你就可以完成第1个月的SQL Server性能调优培训了。今天我将讲下页的一些限制,还有为什么你会喜欢这些限制,同时也会讨厌这些限制。

正如你在第2周学到的,数据页始终是8kb 的大小,而且你只能在上面存储8060 bytes。你的记录大小指示你在一个页里可以存储多少记录。当你与像CHAR,INT,DATETIME等定长类型数据类型打交道时,你会发现SQL Server有记录长度不能超过8060 bytes长度(包含7 bytes 的内部行开销)的限制。

页面限制——好的一面

当你的表少于8列时,你需要(为每条记录)增加额外7 bytes 的内部行开销。对每增加的8列都要增加额外的1 byte, 例如,17列,你需要9 btyes的内部行开销(7+1+1)。如果你尝试创建更长的记录大小,SQL Server会在你执行CREATE TABLE语句时返回一个错误信息给你。来看看下面的表定义:

1 CREATE TABLE TooLargeTable1
2 (
3    Column1 CHAR(5000),
4    Column2 CHAR(3000),
5    Column3 CHAR(54)
6 )
7 GO

正如你所见,每条记录需要8061 bytes(5000+3000+54+7 bytes)。因此在这种情况下,当你尝试去创建这个表时,SQL Server会返回下列的错误信息。

当你创建超过8列的表时,你需要把SQL Server需要的8 bytes的行内部开销也算进去。

1 CREATE TABLE TooLargeTable2
2 (
3    Column1 CHAR(1000) NOT NULL,   Column2 CHAR(1000) NOT NULL,
4    Column3 CHAR(1000) NOT NULL,   Column4 CHAR(1000) NOT NULL,
5    Column5 CHAR(1000) NOT NULL,   Column6 CHAR(1000) NOT NULL,
6    Column7 CHAR(1000) NOT NULL,   Column8 CHAR(1000) NOT NULL,
7    Column9 CHAR(53) NOT NULL
8 )
9 GO

因此这里又是一个非法的表定义(8000+53+8 bytes),这里SQL Server会返回一个错误信息。

页面限制——坏的一面

在上一环节我已经向你展示了页面限制你喜欢的一面,因为当你在创建这样表的时候,SQL Server会返回你一个错误信息。但是页面限制也有你讨厌的一面,因为SQL Server会允许你创建这样的表,而且有时INSERT语句执行成功,有时却会失败……我们来看下。

这里我们面对的问题是与像VARCHAR等变长数据类型。当这些列不能存在它本身页时,SQL Server会把它们移动到在另外页面的行偏移位置。这个被称为 行溢出页(Row-Overflow page)。SQL Server会在原来的页面留下24 bytes长的指向行溢出页的指针。

在于其他列组合时的某些情况下,这个指针会溢出8060 bytes的限制。我们来看下下面的表定义:

1 CREATE TABLE TooLargeTable3
2 (
3    Column1 CHAR(5000),
4    Column2 CHAR(3000),
5    Column3 CHAR(30),
6    Column4 VARCHAR(3000)
7 )
8 GO

如你所见,这里我使用了VARCHAR(3000)的数据类型。你会看到SQL Server这里会给你一个警告信息。这个警告提示你可以创建这个表,但在执行INSERT/UPDATE语句时可能会失败……

下面在表里的插入语句会成功:

1 INSERT INTO TooLargeTable3 VALUES
2 (
3    REPLICATE(‘x‘, 5000),
4    REPLICATE(‘x‘, 3000),
5    REPLICATE(‘x‘, 30),
6    REPLICATE(‘x‘, 19)
7 )
8 GO

这里的记录大小是8056 bytes长(5000+3000+30+19+7 bytes)。在这个情况下,SQL Server会把第4列的数据保存在主数据页。但是想像下下面的INSERT语句:

1 INSERT INTO TooLargeTable3 VALUES
2 (
3    REPLICATE(‘x‘, 5000),
4    REPLICATE(‘x‘, 3000),
5    REPLICATE(‘x‘, 30),
6    REPLICATE(‘x‘, 3000)
7 )
8 GO 

在刚才的INSERT语句,SQL Server会把第4列数据移到行溢出页(row-overflow page),因为这3000 bytes 不能在主数据页里放下。这也就意味着SQL Server会在这里留下一个指向不同页且24bytes 长的指针,在那个位置可以找到数据。但是我们的记录大小现在是8061 bytes长(5000+3000+30+24+7 bytes)。

Duang,你的记录长度超过8060 bytes,INSERT语句执行失败了!

这些就是坏的限制,因为他们在数据库操作的时候隐藏着,好的一面就是在你定义表架构的时候如上所示可见的。想想看是啥?

小结

在你设计你的表结构时,你要非常仔细的想下你的操作。在SQL Server里与页打交道时你会碰到很多这样的执行进去后才出现的限制。当然,在SQL Server给你错误信息时,你不允许创建这个表,基本上就天下太平了。

当当你收到警告时,基本上每个人会想不都不想下就忽略掉。这始终是个坏的操作,因为你已经看到了,你的INSERT可能在运行时失败,问题的发生你是可以预见的。我希望你现在已经明白这个性能调优培训是个很好内幕公开,并且为什么理解数据页的内部结构是多么重要!

在接下来的培训我会讲解SQL Server中堆表的更多细节,还有为什么它们有时是好的(设计),有时候却是不好的(设计)。请继续关注,并且好好享受剩下的7天!

时间: 2024-08-08 12:01:13

第4周 页面限制8060 bytes的相关文章

SQL Server 性能调优培训引言

原文:SQL Server 性能调优培训引言 大家好,这是我在博客园写的第一篇博文,之所以要开这个博客,是我对MS SQL技术学习的一个兴趣记录. 作为计算机专业毕业的人,自己对技术的掌握总是觉得很肤浅,博而不专,到现在我才发现自己的兴趣所在,于是我通过网络找了各种MS SQL技术的相关文档,总觉得讲得比较干涩,没有一个系统性,今年3月底我无意浏览到一个网站提供免费的性能调优的半年培训(http://www.sqlpassion.at/academy/performance-tuning-tra

对于大于8046 bytes的行,RCSI/SI事务隔离级别无效

自SQL Server 2005起,我们有了READ COMMITTED SNAPSHOT ISOLATION level (RCSI) 和SNAPSHOT ISOLATION level (SI)两个事务隔离级别.当你使用这些事务隔离级别时,读操作(SELECT语句)在读的时候不需要S锁(共享锁),写操作(UPDATE,DELETE语句)会对记录进行版本控制,这些改变会写入TempDb.它们就会生成一个版本链,记录的最新版本(存在数据库里的数据页里)指向存在TempDb里的页,下图可以帮助我们

SQL Server :理解数据页结构

我们都很清楚SQL Server用8KB 的页来存储数据,并且在SQL Server里磁盘 I/O 操作在页级执行.也就是说,SQL Server 读取或写入所有数据页.页有不同的类型,像数据页,GAM,SGAM等.在这文章里,让我们一起来理解下数据页结构. SQL Server把数据记录存在数据页(Data Page)里.数据记录是堆表里.聚集索引里叶子节点的行. 数据页由3个部分组成.页头(标头),数据区(数据行和可用空间)及行偏移数组. 在我们讨论在SQL Server里,数据页内部结构具

使用SQL Server 2014内存数据库时需要注意的地方

本文从产品设计和架构角度分享了Microsoft内存数据库方面的使用经验,希望你在阅读本文之后能够了解这些新的对象.概念,从而更好地设计你的架构. 内存数据库,指的是将数据库的数据放在内存中直接操作.相对于存放在磁盘上,内存的数据读写速度要高出很多,故可以提高应用的性能.微软的SQL Server 2014已于2014年4月1日正式发布,SQL 2014一个主要的功能即为内存数据库. 下面,我将着重介绍使用SQL Server 2014内存数据库时需要注意的地方. SQL Server 2014

[转]Disk Space Usage and SQL Server Performance

Disk Space Usage and SQL Server Performance By Gregory A. Larsen When you think of SQL Server performance components, you think of the usage of CPU, memory, and the I/O it takes to process a query. However, there is another component you should consi

Json与JsonPath

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,因为它良好的可读性与易于机器进行解析和生成等特性,在当前的数据整理和收集中得到了广泛的应用. JSON和XML相比较可谓不相上下. Python 2.X中自带了JSON模块,直接import json就可以使用了. 官方文档:http://docs.python.org/library/json.html Json在线解析网站:http://www.json.cn JSONjson简单来说就是JavaSc

SQL Server 2014 内存优化表

不同于disk-based table,内存优化表驻留在内存中,使用 Hekaton 内存数据库引擎实现.在查询时,从内存中读取数据行:在更新时,将数据的更新直接写入到内存中.内存优化表能够在disk上维护一个副本,用于持久化数据集. Memory-optimized tables reside in memory. Rows in the table are read from and written to memory. The entire table resides in memory.

爬虫——json模块与jsonpath模块

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写.同时也方便了机器进行解析和生成.适用于进行数据交互的场景,比如网站前台与后台之间的数据交互. JSON和XML相比较可谓不相上下. Python 3.X中自带了JSON模块,直接import json就可以使用了. 官方文档:http://docs.python.org/library/json.html Json在线解析网站:http://www.json.cn/# J

MSSQL修改表字段

修改表(将某列长度增加),此时原有的列不会被真正替换,而是是将新列加到该表最后,我们可以使用DBCC PAGE查看原油的数据仍然在那里. 示例: use tempdb go create table a(col1 smallint, col2 char(2000), col3 char(1000) ) 此时在表a上修改列col2为char(3000) alter table a alter column col2 char(3000) 在我们理解中,该表目前单行数据长度4002再加内部使用的一点