none
微软的技术贪乏了吗? RRS feed

  • 问题

  • SQL Server 2005是微软五年磨一剑的产品,推出之后赞誉声一片。确实,相比sql server 2000,2005有了长足的进步,算是从娃娃长大成人了,可是,一些儿时的坏习惯,依然如故啊。

     

    在SQL Server 2000中,数据行不能跨越页边界(参考: http://ningoo.itpub.net/post/2149/205525 ),所以限制了一行数据最大只能8060字节,到了2005,微软对于字符类型做了改进,号称原来8k的varchar,通过新的varchar(max)可以支持到2G大小,从此可以使用varchar(max)来替代text了,好消息。

    可是,数据行的限制呢?依然存在,不知道这个历史遗留问题,是修改的难度太大,还是微软故意忽视了?

    create table big(a char(4000),b char(4000),c char(4000))

    Msg 1701, Level 16, State 1, Line 3
    Creating or altering table 'big' failed because the minimum row size would be 12007, including 7 bytes of internal overhead. This exceeds the maximum allowable table row size of 8060 bytes.

    显然,微软对于varchar(max)类型做了另外的处理,应该是象Oracle的行外LOB一样,在数据行中存了一个指针指向varchar(max)实际存储位置。既然已经能实现行数据链接,为什么还要将行限制在一个页内?

    2009年9月27日 15:42

答案

全部回复

  • How stick on fixed length column when there's way around?

    2009年9月27日 18:10
  • create table big(a char(4000),b char(4000),c varchar(4000))
    好像唯一的解决办法就是把其中一个改成varchar,让他移动到 ROW_OVERFLOW_DATA 分配单元的另一页上。
    确实好像不能像楼主说的突破一页。SQL2008也是如此。
    2009年9月28日 2:06
    版主
  • 改为Varchar


    Try SQL Server 2008 QQ:315054403 dgdba@hotmail.com
    2009年9月28日 2:07
  • 2009年9月28日 2:09
    版主
  • 这个设计是有道理的

    很难想象一个数据场景需要char(4000)的。

    刚刚学sql数据字段定义的时候,就有人教过一般大于50长度的字符应该使用varchar定义。


    family as water
    2009年9月28日 2:15
  • 另外,每列的长度还是受到8000的限制的:

    1.创建表失败
    create table TestBigTable (char1 varchar(8001) not null)
    --消息 131,级别 15,状态 2,第 1 行
    --赋予 列 'char1' 的大小(8001)超出了任意数据类型的最大允许值(8000)。
    

    2.创建表插入数据都成功,但截断成8000了

    create table TestBigTable (char1 varchar(max) not null)
    --(1 行受影响)
    insert TestBigTable (char1) select replicate('a',8004)
    --(1 行受影响)
    select LEN(char1) as len from TestBigTable
    /*len
    --------------------
    8000
    (1 行受影响)
    */
    2009年9月28日 2:20
    版主
  • 看来理解 8KB 限制 对SQL server 来说还是有很大意义的。

    8K 是个有魔力的值,是SQL读写数据的基本单位,底层设计就是这样不是随便改得了的。
    硬盘要64K分区也是以这个为基础来的吧?

    hello
    2009年9月28日 3:07
  • Yes because smallest unit sql reads/wriets from/to disk is extent (8 x 8k pages).
    2009年9月28日 3:10
  • 哈哈我也是一知半解的,可能应该说是 
    8K的页是保存数据的基本单位,
    64K的extent(这个叫啥?篇?)才是读写的基本单位
    hello
    2009年9月28日 3:14
  • 中文就是区。
    页是 SQL Server 中数据存储的基本单位。
    区是由8个物理上连续的页构成的集合。区有助于有效管理页。所有页都存储在区中。

    另外,个人也觉得功能和性能是要权衡的。考虑扩展功能的同时,更需要兼顾对常用功能的性能影响。譬如前面我们讨论的8060和8000的限制,毕竟一般情况不会超过这几个值的。
    有些非常规的,还是需要结构调整、应用程序开发配合一起做的。数据库也不是万能的。

    2009年9月28日 3:39
    版主