• 第4/24周 页面限制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天!

    围观PPT: 

    0511_04页面限制8060_bytes.rar

  • 相关阅读:
    使用POI读取excel文件内容
    有序链表
    jQuery Validate验证框架详解
    怎样在VS2010中打开VS2012的项目
    在Win8.1系统下如何安装运行SQL Server 2005
    SQL2005 2008配置错误,无法识别的配置节 system.serviceModel machine.config配置文件有问题
    深入浅出学Spring Data JPA
    Java 学习摘要
    JFinal
    spring 4 + jpa(hibernate 3/4) + spring mvc 多数据源配置
  • 原文地址:https://www.cnblogs.com/woodytu/p/4467805.html
Copyright © 2020-2023  润新知