NULL与“”的存储空间
引子
部门例会,讨论起数据库的NULL和“” 是否相同,本人真心认为不同,但对于报表把NULL显示成“”来说,又只能是一样的。矛盾:(
但对于一个可空的字段,取值NULL和“”空间占用是否相同,这个必须深入数据库存储来看才能深刻知道 (如果没有特殊说明,数据库指的是SQLServer) 。
分析
首先建立一个临时表
CREATE TABLEA( a INTNOTNULL, b CHAR(8)NULL, c nvarchar(200)NULL, d NVARCHAR(200)NULL ) INSERT A(a,b,c,d)VALUES(0xcccccccc,NULL,NULL,'CC') INSERT A(a,b,c,d)VALUES(0xdddddddd,'','','DD')
|
通过执行
dbcctraceon(3604)
dbccind('tempdb','A',-1)
可以得到如下:
有了1:150 有可以通过如下语句
dbccpage('tempdb',1,150,1)
得到记录的二进制存储结构
PAGE: (1:150)
BUFFER:
BUF @0x00000008620D2DC0
bpage = 0x000000071D940000 bhash = 0x0000000000000000 bpageno = (1:150) bdbid = 2 breferences = 0 bcputicks = 0 bsampleCount = 0 bUse1 = 47930 bstat = 0x10b blog = 0xab215acc bnext = 0x0000000000000000
PAGE HEADER:
Page @0x000000071D940000
m_pageId = (1:150) m_headerVersion = 1 m_type = 1 m_typeFlagBits = 0x0 m_level = 0 m_flagBits = 0x8000 m_objId (AllocUnitId.idObj) = 5084 m_indexId (AllocUnitId.idInd) = 2304 Metadata: AllocUnitId = 648518346674536448 Metadata: PartitionId = 648518346670145536 Metadata: IndexId = 0 Metadata: ObjectId = 325576198 m_prevPage = (0:0) m_nextPage = (0:0) pminlen = 16 m_slotCnt = 2 m_freeCnt = 8034 m_freeData = 154 m_reservedCnt = 0 m_lsn = (34:1940:35) m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0 m_tornBits = 0 DB Frag ID = 1
Allocation Status
GAM (1:2) = ALLOCATED SGAM (1:3) = ALLOCATED PFS (1:1) = 0x61 MIXED_EXT ALLOCATED 50_PCT_FULL DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED
DATA:
Slot 0, Offset 0x60, Length 29, DumpStyle BYTE
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS Record Size = 29 Memory Dump @0x000000003881A060
0000000000000000: 30001000 cccccccc 00000000 00000000 04000602 0................... 0000000000000014: 0019001d 00430043 00 .....C.C.
Slot 1, Offset 0x7d, Length 29, DumpStyle BYTE
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS Record Size = 29 Memory Dump @0x000000003881A07D
0000000000000000: 30001000 dddddddd 20202020 20202020 04000002 0....... .... 0000000000000014: 0019001d 00440044 00 .....D.D.
OFFSET TABLE:
Row - Offset 1 (0x1) - 125 (0x7d) 0 (0x0) - 96 (0x60)
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
|
看到这只能翻开书继续
首先一个SQLServer数据库页的结构如下:
数据行里每一条记录的格式如下:
通过上面信息,分析数据如下:
蓝1,蓝2: 状态位
蓝3:列数偏移 0010 指向 蓝6的位置
蓝4:a字段的内容
蓝5:b字段空间, 蓝7 0000110 (第二列和第三列为空)
蓝6:列个数 0004 (4列)
蓝7: NULL的位掩图
蓝8:可变列数
蓝9:第一个可变结束位置 (0019)25
蓝10:第二个可变结束位置 (001d) 29
蓝11: 43004300 (d字段内容为“CC”)
红1,红2: 状态位
红3:列数偏移 0010 指向 红6的位置
红4:a字段的内容
红5:b字段空间
红6:列个数 0004 (4列)
红7: NULL位掩图 0000110 (第二列和第三列为空)
红8:可变列数
红9:第一个可变结束位置 (0019)25
红10:第二个可变结束位置 (001d) 29
红11: 43004300 (d字段内容为“DD”)
红5和蓝5 内容不一样,但空间一样(可空固定长度的b字段)
红9和蓝9 内容一样,但红7和蓝7:的NULL位掩图不一样(可空非固定长度的c字段)
结论
对于一个可空字段来说,SQLServer的NULL和“”所占用空间是一样的。