zoukankan      html  css  js  c++  java
  • [译]SQL Passion Week 4: 数据页的限制

    SQL Passion Week 4: 数据页的限制

      在week2的时候我们知道了数据页是8kb的大小,可以存储8060 bytes的数据. 单条记录的长度决定了一个页上能存储多少条记录. 当我们处理固定长度类型字段(char,int,datetime等)时, 有一个限制就是总长度不能超过8060 bytes,包括其overhead.

      限制 - 好的情况

      当我们的表少于8列时, 页内部需要添加一个7bytes的overhead.  当每多8个列, 就会额外添加一个1bytes的overhead. 举个例子, 一个表有17个列, 那它在页中存储的每行记录都要有9bytes的overhead(7 + 1 + 1). 如果尝试创建一个列总长度超过8060bytes的表, SQL Server会报出错误信息.

      

    CREATE TABLE TooLargeTable1
    (
       Column1 CHAR(5000),
       Column2 CHAR(3000),
       Column3 CHAR(54)
    )
    GO

      这段代码创建的表,每条记录的长度都是8061 bytes (5000 + 3000 + 54 + 7), 所以我们执行时就会返回以下错误信息:

      

      再试一个超过8列的表

      

    CREATE TABLE TooLargeTable2
    (
       Column1 CHAR(1000) NOT NULL,
       Column2 CHAR(1000) NOT NULL,
       Column3 CHAR(1000) NOT NULL,
       Column4 CHAR(1000) NOT NULL,
       Column5 CHAR(1000) NOT NULL,
       Column6 CHAR(1000) NOT NULL,
       Column7 CHAR(1000) NOT NULL,
       Column8 CHAR(1000) NOT NULL,
       Column9 CHAR(53) NOT NULL
    )
    GO 

      这个表的长度是( 8000 + 53 + 7 + 1), 所以也会报错.

      限制 - 坏的情况

       上面一段展示了SQL Server好的一面,提示了我们不能创建超过长度的表. 但是也有比较坏的情况, 允许我们建表, 但在后续一些操作时却发生了错误.

      这种情况发生在一些变长字段上, 比如varchar. 当这些列无法在本身的数据页里填充时, SQL Server就会把它们转移到别的页上. 我们叫做行溢出页(Row-Overflow Page). 在原本的数据页上, 会留下一个24bytes的指针指向行溢出页的地址.  某些情况, 这个指针可能会造成总列长度超过8060总长度限制. 我们看下面的例子:

      

    CREATE TABLE TooLargeTable3
    (
       Column1 CHAR(5000),
       Column2 CHAR(3000),
       Column3 CHAR(30),
       Column4 VARCHAR(3000)
    )
    GO

      这里我们包含了一个varchar(3000)的列, 在创建表时SQL Server仅仅给了我们一个warning, 并没有阻止.

      

      然后我们插入一条数据, 

    INSERT INTO TooLargeTable3 VALUES
    (
       REPLICATE('x', 5000),
       REPLICATE('x', 3000),
       REPLICATE('x', 30),
       REPLICATE('x', 19)
    )
    GO 

      总长度是 8056 (5000 + 3000 + 30 + 19 + 7 ), 没有问题.

      我们再插入第二条:

      

    INSERT INTO TooLargeTable3 VALUES
    (
       REPLICATE('x', 5000),
       REPLICATE('x', 3000),
       REPLICATE('x', 30),
       REPLICATE('x', 3000)
    )
    GO 

      区别是第四列, 我们变成了3000bytes的值, 总长度超出8060, 这就引发了行溢出页的机制, SQL Server把这3000长度的值存储到了行溢出页上, 而在原本的数据页上留下一个 24 bytes的指针. 因此我们的记录长度现在变成了8061 bytes (5000 + 3000 + 30 + 24 + 7 ).

      于是插入失败.

      这就是比较坏的情况, 因为它在我们做数据库操作时才开始抛错. 好的机制应该是在我们定义表结构时就应该预见这些错误并阻止.

      当我们在设计表结构时, 应该非常小心, 数据库中有大量的限制. 当SQL Server给我们报出错误提示还好, 但如果只是一个warning, 多数人可能会不经考虑就忽略它们. 而到了运行期后, 简单一个insert错误就会给我们带来大麻烦.

  • 相关阅读:
    idea 安装lombok 插件过程
    typora快捷键之速成笔记
    Android端抓取日志
    接口测试Case之面向页面对象编写及规范
    Jenkins + jmeter + ant + git 自动化集成
    自动化测试使用流程
    Jenkins git 的配置及问题解决
    传智springMVC笔记
    session 原理 数据结构
    Redis 3.0 集群搭建
  • 原文地址:https://www.cnblogs.com/alphaqcode/p/4988661.html
Copyright © 2011-2022 走看看