加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

NULL在SQLServer数据库数据文件中的存储

发布时间:2020-12-12 15:41:19 所属栏目:MsSql教程 来源:网络整理
导读:? 这个对于定长和不定长字段来说是两个结果 定长字段Null要占足字段空间,不定长字段则不占空间,两者都是通过null_bitmap来确认行数据中的null列。这个很容易用事实表的大小来验证。其具体存储机制还是需要dbcc来查看数据页。我们分几种情况查看: ? ? ? ?

?

这个对于定长和不定长字段来说是两个结果
定长字段Null要占足字段空间,不定长字段则不占空间,两者都是通过null_bitmap来确认行数据中的null列。这个很容易用事实表的大小来验证。其具体存储机制还是需要dbcc来查看数据页。我们分几种情况查看:

?

?


?

?

-- 定长测试:

-- 建立测试环境

create database dbtest111

go

use dbtest111

go

create table t1( id char ( 10) , name char ( 10))

insert into t1 select 'a' , '1'

insert into t1 select 'b' , '2'

?

create table t2( id char ( 10) , name char ( 10))

?

insert into t2 select 'a' , 'jinjazz1'

insert into t2 select 'b' ,null

insert into t2 select 'c' ,null

insert into t2 select 'd' , 'jinjazz2'

go

-- 运行此命令

dbcc ind( dbtest111, t2, 0)

-- 得到 pagetype=1 的那个行数据的 pageid ,比如我这里是

?

dbcc traceon( 3604)

dbcc page( dbtest111, 1, 89, 1)

?

运行上面的sql语句,创建测试环境和实验脚本。得到如下结果

Slot 0,Offset 0x60,Length 27,DumpStyle BYTE

Record Type = PRIMARY_RECORD??????? Record Attributes =? NULL_BITMAP??
Memory Dump @0x5655C060

00000000:? 10001800 61202020 20202020 20206a69 ?....a??????? ji??????
00000010:? 6e6a617a 7a312020 0200fc ?????????????njazz1? ...????????????

Slot 1,Offset 0x7b,DumpStyle BYTE

Record Type = PRIMARY_RECORD??????? Record Attributes =? NULL_BITMAP??
Memory Dump @0x5655C07B

00000000:? 10001800 62202020 20202020 20206a69 ?....b??????? ji??????
00000010:? 6e6a617a 7a312020 0200fe ?????????????njazz1? ...????????????

Slot 2,Offset 0x96,DumpStyle BYTE

Record Type = PRIMARY_RECORD??????? Record Attributes =? NULL_BITMAP??
Memory Dump @0x5655C096

00000000:? 10001800 63202020 20202020 20206a69 ?....c??????? ji??????
00000010:? 6e6a617a 7a312020 0200fe ?????????????njazz1? ...????????????

Slot 3,Offset 0xb1,DumpStyle BYTE

Record Type = PRIMARY_RECORD??????? Record Attributes =? NULL_BITMAP??
Memory Dump @0x5655C0B1

00000000:? 10001800 64202020 20202020 20206a69 ?....d??????? ji??????
00000010:? 6e6a617a 7a322020 0200fc ?????????????njazz2? ...

?

每个slot都代表一行,可以看到null的不但占用空间,而且还写入了你不要的东西,最后处理是通过红色字体部分来判断那些字段是null哪些不是null,红色部分就是null_bitmap


--2 、不定长字段测试

?

create database dbtest111

go

use dbtest111

go

create table t2( id char ( 10) , name varchar ( 10))

?

insert into t2 select 'a' , 0)

-- 得到 pagetype=1 的那个行数据的 pageid ,比如我这里是

?

?

dbcc traceon( 3604)

dbcc page( dbtest111, 73, 1)

?

运行以上SQL代码得到结果

?

00000000:? 30000e00 61202020 20202020 20200200 ?0...a??????? ..??????
00000010:? fc01001d 006a696e 6a617a7a 31????????.....jinjazz1??????????

Slot 1,Offset 0x7d,Length 17,DumpStyle BYTE

Record Type = PRIMARY_RECORD??????? Record Attributes =? NULL_BITMAP??
Memory Dump @0x5655C07D

00000000:? 10000e00 62202020 20202020 20200200 ?....b??????? ..??????
00000010:? fe???????????????????????????????????.??????????????????????

Slot 2,Offset 0x8e,DumpStyle BYTE

Record Type = PRIMARY_RECORD??????? Record Attributes =? NULL_BITMAP??
Memory Dump @0x5655C08E

00000000:? 10000e00 63202020 20202020 20200200 ?....c??????? ..??????
00000010:? fe???????????????????????????????????.??????????????????????

Slot 3,Offset 0x9f,Length 29,DumpStyle BYTE

Record Type = PRIMARY_RECORD??????? Record Attributes =? NULL_BITMAP VARIABLE_COLUMNS

Memory Dump @0x5655C09F


00000000:? 30000e00 64202020 20202020 20200200 ?0...d??????? ..??????
00000010:? fc01001d 006a696e 6a617a7a 32????????.....jinjazz2

?

varchar比char节省地方,他的rowoffset是依次写入的,null不占用空间,空间利用很好,这个比char字段的null节省地方。


--3 、不定长字段更改

?

update t2 set name = 'jinjazz3' where id= 'b'

dbcc page( dbtest111, 1)

?

/*

Row - Offset??????????????????????

3 (0x3) - 159 (0x9f)??????????????

2 (0x2) - 142 (0x8e)??????????????

1 (0x1) - 188 (0xbc) ???????????????

0 (0x0) - 96 (0x60)?

*/ ?

?

这个只要看最后的row Offset,红色部分是update的这条,他开辟了另外一处空间把null变成了非null。

当然系统会适时回收老的废弃空间。但varchar的效率没有char高是肯定的了,这也就是说char相当于空间换时间了

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读