NULL在SQLServer資料庫資料檔案中的儲存

2021-08-23 13:35:53 字數 3960 閱讀 7660

這個對於定長和不定長欄位來說是兩個結果

定長字段null要佔足字段空間,不定長字段則不佔空間,兩者都是通過null_bitmap來確認行資料中的null列。這個很容易用事實表的大小來驗證。其具體儲存機制還是需要dbcc來檢視資料頁。我們分幾種情況檢視:

-- 定長測試:

-- 建立測試環境

create

database dbtest111 go

usedbtest111 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, length 27, 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, length 27, 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, length 27, 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

usedbtest111 go

create

table t2( id char

( 10)

,name

varchar

( 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, 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, length 17, 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節省地方。

<

NULL在SQLServer資料庫日誌檔案中的儲存

日誌檔案ldf中的null 參考日誌檔案結構 通過null bitmap來確定哪些欄位為null,所以在日誌中null是不佔空間的。下面可以在得到一行二進位制內容,比如通過fn dblog函式或者dbcc checklog,然後檢查此行內容那些是列是null static byte readrowd...

NULL在SQLServer資料庫日誌檔案中的儲存

日誌檔案ldf中的null 參考日誌檔案結構 通過null bitmap來確定哪些欄位為null,所以在日誌中null是不佔空間的。下面可以在得到一行二進位制內容,比如通過fn dblog函式或者dbcc checklog,然後檢查此行內容那些是列是null static byte readrowd...

NULL在SQLServer資料庫日誌檔案中的儲存

日誌檔案ldf中的null 參考日誌檔案結構 通過null bitmap來確定哪些欄位為null,所以在日誌中null是不佔空間的。下面可以在得到一行二進位制內容,比如通過fn dblog函式或者dbcc checklog,然後檢查此行內容那些是列是null static byte readrowd...