2019:
Slot 0, Offset 0x60, Length 4045, DumpStyle BYTE
2020:
Slot 0, Offset 0x60, Length 4047, DumpStyle BYTEnchar类型在存储的时候会+7 byte,,,

解决方案 »

  1.   

    可能结果很难直接算出来,看老大那公式,结果正确--计算每页的行数(每页有 8096 可用字节)
    --2019大小
    select 4047*2=8094
    --2020大写
    select 4049*2=8098为什么页的字节数是8096?不是说8060吗?..
      

  2.   

    哈 看到SELECT  @Null_Bitmap = 2 + ((@Num_Cols + 7) / 8) 
    这是3,再加行标题的4,就是7了
      

  3.   


    页头占了96Byte,剩下的就是存放数据和偏移量了,,,
      

  4.   

    --测试在master库:
    -- 创建2个测试表 
    CREATE TABLE [dbo].[Table_2019]([Data] [nchar](2019) NOT NULL) 
    CREATE TABLE [dbo].[Table_2020]([Data] [nchar](2020) NOT NULL) 
    go 
    -- 填充数据 
    declare @i int 
    set @i = 0 
    while(@i < 20) 
    begin 
        insert Table_2019(Data) values('') 
        insert Table_2020(Data) values('') 
        select @i = @i + 1 
    end 
    go 
    exec sp_spaceused 'Table_2019' 
    go
    exec sp_spaceused 'Table_2020' --结果:
    Table_2019 20          200 KB 160 KB 8 KB 32 KB
    Table_2020 20          200 KB 160 KB 8 KB 32 KB
    --测试在tempdb库:
    -- 创建2个测试表 
    CREATE TABLE [dbo].[Table_2019]([Data] [nchar](2019) NOT NULL) 
    CREATE TABLE [dbo].[Table_2020]([Data] [nchar](2020) NOT NULL) 
    go 
    -- 填充数据 
    declare @i int 
    set @i = 0 
    while(@i < 20) 
    begin 
        insert Table_2019(Data) values('') 
        insert Table_2020(Data) values('') 
        select @i = @i + 1 
    end 
    go 
    exec sp_spaceused 'Table_2019' 
    go
    exec sp_spaceused 'Table_2020' 
    goTable_2019 20          136 KB 80 KB 8 KB 48 KB
    Table_2020 20          200 KB 160 KB 8 KB 32 KB
      

  5.   

    数据页 8K = 8192 - 页头(96) = 8096而数据可用 8060 这个是常规说法, 实际上不变长和定长, 是否允许 NULL 值决定了每个列的额外开销在前面给出的计算方法中有提到这个(变长列的开销参考联机帮助上的说法)楼主的表是定长的, 不允许NULL值, 会少一些额外的开销, 故可存储数据的空间大一些
      

  6.   

    就是看完美mm的blog,才去查的资料 ~
      

  7.   

    老大,我去了not null后用1或111试了一下sp_spaceused结果和有not null一样
      

  8.   


    仔细看联机帮助上的算法:保留行中称为空位图的部分以管理列的为空性。计算大小:
    Null_Bitmap = 2 + ((Num_Cols + 7) / 8)只应使用该表达式的整数部分。而去掉其余部分。
      

  9.   

    22楼的还没有想到是什么原因, 除了 master/msdb, 其他库都是符合联机帮助上的计算规则的
      

  10.   


    22楼的测试,是在2005下吗,2000的master库计算是正常的。
      

  11.   

    2019 * 2 + 3  +  4 + 2 = 4047
    3 -- 2 + ((总列数+ 7) / 8) = 2+ (1+7)/8  = 3
    4 -- 是数据行的行标题开销
    2 -- 是计算行数时引入的行大小余量
    4047 * 2 = 8094 2020 * 2 + 3  +  4 + 2 = 4049
    3 -- 2 + ((总列数+ 7) / 8) = 2+ (1+7)/8  = 3
    4 -- 是数据行的行标题开销
    2 -- 是计算行数时引入的行大小余量4049 * 2 = 8098 --->每页有 8096 可用字节--->
    第一个一页可两行
    第二个一页只能一行
     
      

  12.   


    是 Ceiling(总列数/8.),每一个 Bit 指示一个字段的 NULL BITMAP.一个Byte可以指示8个字段的null bitmap状态。
      

  13.   

    (x + 7) / 8
    原来是为了实现?resutl = x%8==0? x/8 : 1+(x-x%8)/8
      

  14.   

    靠,你真牛,绕来绕去的。其实意思就是最少都要使用1个byte来指定null bitmap.
      

  15.   


    针对22楼的测试,我研究了一下,发现是Rowversing的原因造成的。在数据库打开"ALLOW_SNAPSHOT_ISOLATION" 选项后,为了做到rowversing,数据页中的每一行必须加上额外的14byte来跟踪行版本的指针。即行大小由原来的4047变成4061,一页只能存1行了。默认情况下,master & msdb两个库的ALLOW_SNAPSHOT_ISOLATION都是打开的。
    --可以用这个查看每个库的rowversing是否打开
    SELECT  name, 
            snapshot_isolation_state_desc,
            is_read_committed_snapshot_on , *
    FROM sys.databases;
    ---验证方法:可以将AdventureWorks库打开ALLOW_SNAPSHOT_ISOLATION,在里面建Table_2019、 Table_2020,然后再看spaceused.ALTER DATABASE ADVENTUREWORKS SET ALLOW_SNAPSHOT_ISOLATION ON;
    GO
    --测试在master库:
    -- 创建2个测试表 
    CREATE TABLE [dbo].[Table_2019]([Data] [nchar](2019) NOT NULL) 
    CREATE TABLE [dbo].[Table_2020]([Data] [nchar](2020) NOT NULL) 
    go 
    -- 填充数据 
    declare @i int 
    set @i = 0 
    while(@i < 20) 
    begin 
        insert Table_2019(Data) values('') 
        insert Table_2020(Data) values('') 
        select @i = @i + 1 
    end 
    go 
    exec sp_spaceused 'Table_2019' 
    go
    exec sp_spaceused 'Table_2020' 
     
    /*--结果:
    Table_2019    20             200 KB    160 KB    8 KB    32 KB
    Table_2020    20             200 KB    160 KB    8 KB    32 KB*/