最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識(shí)百科 - 正文

SQLSERVER中數(shù)據(jù)行所占用的最小空間

來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-09 07:52:12
文檔

SQLSERVER中數(shù)據(jù)行所占用的最小空間

SQLSERVER中數(shù)據(jù)行所占用的最小空間:數(shù)據(jù)行所占的最小空間是多少呢? 先來看看下面這張經(jīng)典數(shù)據(jù)行結(jié)構(gòu)圖(引自Inside Sql Server) 因?yàn)榭勺冮L(zhǎng)度類型的列會(huì)有額外的空間開銷,所以不考慮可變長(zhǎng)度的字段。 現(xiàn)在計(jì)算一下除去實(shí)際數(shù)據(jù)后每個(gè)數(shù)據(jù)行所需要占用的空間: 狀態(tài)位A占一個(gè)字節(jié),狀態(tài)位B占
推薦度:
導(dǎo)讀SQLSERVER中數(shù)據(jù)行所占用的最小空間:數(shù)據(jù)行所占的最小空間是多少呢? 先來看看下面這張經(jīng)典數(shù)據(jù)行結(jié)構(gòu)圖(引自Inside Sql Server) 因?yàn)榭勺冮L(zhǎng)度類型的列會(huì)有額外的空間開銷,所以不考慮可變長(zhǎng)度的字段。 現(xiàn)在計(jì)算一下除去實(shí)際數(shù)據(jù)后每個(gè)數(shù)據(jù)行所需要占用的空間: 狀態(tài)位A占一個(gè)字節(jié),狀態(tài)位B占

數(shù)據(jù)行所占的最小空間是多少呢? 先來看看下面這張經(jīng)典數(shù)據(jù)行結(jié)構(gòu)圖(引自Inside Sql Server) 因?yàn)榭勺冮L(zhǎng)度類型的列會(huì)有額外的空間開銷,所以不考慮可變長(zhǎng)度的字段。 現(xiàn)在計(jì)算一下除去實(shí)際數(shù)據(jù)后每個(gè)數(shù)據(jù)行所需要占用的空間: 狀態(tài)位A占一個(gè)字節(jié),狀態(tài)位B占

數(shù)據(jù)行所占的最小空間是多少呢?

先來看看下面這張經(jīng)典數(shù)據(jù)行結(jié)構(gòu)圖(引自Inside Sql Server)



因?yàn)榭勺冮L(zhǎng)度類型的列會(huì)有額外的空間開銷,所以不考慮可變長(zhǎng)度的字段。 現(xiàn)在計(jì)算一下除去實(shí)際數(shù)據(jù)后每個(gè)數(shù)據(jù)行所需要占用的空間:

狀態(tài)位A占一個(gè)字節(jié),狀態(tài)位B占1個(gè)字節(jié),用于標(biāo)識(shí)固定字段長(zhǎng)度的占2個(gè)字節(jié),標(biāo)識(shí)固定列數(shù)量的占去2個(gè)字節(jié),NULL位圖至少占用1個(gè)字節(jié)。
這樣算下來:1+1+2+2+1=7。 也就是在不考慮實(shí)際數(shù)據(jù)的情況下一個(gè)數(shù)據(jù)行最少要占用7個(gè)字節(jié)。如果實(shí)際數(shù)據(jù)長(zhǎng)度為1,那么每一行所占用的空間就為8個(gè)字節(jié)。真的是這樣嗎?

現(xiàn)在做個(gè)實(shí)驗(yàn)驗(yàn)證一下,在下文中如果沒有特殊的說明,所有的敘述都是以數(shù)據(jù)表沒有建立聚集索引為前提的。

創(chuàng)建一個(gè)表:
Create Table table1
(
col1 char(1)
)

插入2行數(shù)據(jù):
insertinto table11 values('a')
insertinto table11 values('b')

然后使用DBCC PAGE命令察看表的結(jié)構(gòu)(為了方便察看,我只保留了Data和Offset Table部分)

DATA:

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

Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP

Memory Dump @0x44EFC060

00000000: 10000500 610100fe 08†††††††††††††††††....a....

Slot 1, Offset 0x69, Length 9, DumpStyle BYTE

Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP

Memory Dump @0x44EFC069

00000000: 10000500 620100fe 08†††††††††††††††††....b....

OFFSET TABLE:

Row - Offset

1 (0x1) - 105 (0x69)

0 (0x0) - 96 (0x60)


Length 后面為9,也就是說每個(gè)數(shù)據(jù)行占了9個(gè)字節(jié),通過offset table部分我們也可以計(jì)算出每個(gè)數(shù)據(jù)行占用了9個(gè)字節(jié)。而不是我們所計(jì)算的8個(gè)字節(jié)?,F(xiàn)在察看以下數(shù)據(jù)行到底存儲(chǔ)了什么內(nèi)容,我們以slot0為例:

10000500 610100fe 08†††††††††††††††††....a....

前兩位10表示沒有可變長(zhǎng)度的字段,后面兩位00在sqlserver 2005中沒有用到;0500表示固定長(zhǎng)度的字段所占的長(zhǎng)度為5(實(shí)際長(zhǎng)度加4);61轉(zhuǎn)換為十進(jìn)制數(shù)位97,表示小寫字母a。后面的0100表示固定長(zhǎng)度的字段數(shù)量為1;剩下fe就是NULL位圖了,翻譯成2進(jìn)制數(shù)為1111 1110,這說明該行中沒有字段為NULL,這和實(shí)際情況也是相符的。那么最后兩位08代表什么呢?在公開答案之前再作一個(gè)試驗(yàn)


創(chuàng)建一個(gè)表:
Create Table table1
(
col1 char(2)
)

像表內(nèi)插入2行數(shù)據(jù):
insertinto table11 values('aa')
insertinto table11 values('bb')

然后使用DBCC PAGE命令察看表的結(jié)構(gòu)(為了方便察看,我只保留了Data和Offset Table部分)

DATA:

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

Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP

Memory Dump @0x4500C060

00000000: 10000600 61610100 fe†††††††††††††††††....aa...

Slot 1, Offset 0x69, Length 9, DumpStyle BYTE

Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP

Memory Dump @0x4500C069

00000000: 10000600 62620100 fe†††††††††††††††††....bb...

OFFSET TABLE:

Row - Offset

1 (0x1) - 105 (0x69)

0 (0x0) - 96 (0x60)



現(xiàn)在看一下char(2)的存儲(chǔ)情況,通過Length和offset table 可以看到,數(shù)據(jù)行的長(zhǎng)度仍然為9。分析一下具體的數(shù)據(jù)行,仍然以slot 0為例:
10000600 61610100 fe†††††††††††††††††....aa...

前兩位10表示沒有可變長(zhǎng)度的字段,后面兩位00在sqlserver 2005中沒有用到;0600表示固定長(zhǎng)度的字段所占的長(zhǎng)度為5(實(shí)際長(zhǎng)度加4);61轉(zhuǎn)換為十進(jìn)制數(shù)位97,表示小寫字母a。后面的0100表示固定長(zhǎng)度的字段數(shù)量為1;剩下fe就是NULL位圖了,翻譯成2進(jìn)制數(shù)為1111 1110,這說明該行中沒有字段為NULL,這和實(shí)際情況也是相符的。

通過上面兩個(gè)實(shí)驗(yàn)可以看出:只有一個(gè)字段,并且類型和長(zhǎng)度為char(1)的表的數(shù)據(jù)行所占用的空間和只有一個(gè)字段,并且類型和長(zhǎng)度為char(2)的表的數(shù)據(jù)行所占用的空間是相等的。為什么會(huì)出現(xiàn)這種情況呢?

實(shí)際上,如果一個(gè)數(shù)據(jù)行的長(zhǎng)度沒有達(dá)到規(guī)定的最小長(zhǎng)度(9 bytes),SQL SERVER會(huì)自動(dòng)在該行的后面填充一個(gè)字節(jié),將長(zhǎng)度擴(kuò)展到9。這就是我們之前看到的那個(gè)08出現(xiàn)的原因。所以SQLSERVER數(shù)據(jù)行最小的長(zhǎng)度為9,而不是8。

您可能要問了:為什么SQL SERVER會(huì)有這樣的規(guī)定呢?

這個(gè)規(guī)定是為了更新操作(update)建立的龜腚。我們知道RID用來標(biāo)識(shí)數(shù)據(jù)頁數(shù)據(jù)行,當(dāng)數(shù)據(jù)頁中的某一行數(shù)據(jù)被更新以至于現(xiàn)有的數(shù)據(jù)頁無法再容納該行時(shí),SQLSERVER會(huì)將該行移動(dòng)到新的數(shù)據(jù)頁中。原有的數(shù)據(jù)行位置并不被其他的數(shù)據(jù)行占用,而是替換成一個(gè)forwarding pointer。該pointer指向那個(gè)被更新的數(shù)據(jù)行的新的位置。而這個(gè)pointer大小為9 byte(header占一byte,RID占8byte,RID的構(gòu)成:4個(gè)字節(jié)的pageID,2個(gè)字節(jié)的fileID,2個(gè)字節(jié)的slotID)。所以sql server為了保證能夠成功地將數(shù)據(jù)行替換成forwarding pointer,規(guī)定每個(gè)數(shù)據(jù)行要最少要占用9個(gè)byte。

您可能又要問了,為什么需要那個(gè)鳥forwarding pointer呢,直接移動(dòng)不就ok了。反正數(shù)據(jù)頁和數(shù)據(jù)頁之間是沒有關(guān)系的,數(shù)據(jù)頁中的數(shù)據(jù)行又是無序的。要那個(gè)forwarding pointer有啥用???

原因是這樣的,當(dāng)數(shù)據(jù)頁中的某一行數(shù)據(jù)被更新以至于現(xiàn)有的數(shù)據(jù)頁無法再容納該行時(shí),SQLSERVER會(huì)將該行移動(dòng)到新的數(shù)據(jù)頁中。之后就出現(xiàn)了兩個(gè)選擇:

1 更新原有數(shù)據(jù)頁中所有數(shù)據(jù)行的RID,這可能是個(gè)非常昂貴的操作(可能有249個(gè)索引)。
2 不更新數(shù)據(jù)頁中的RID,將那個(gè)空缺的位置替換成一個(gè)forwarding pointer。在以后的查詢時(shí)按照這個(gè)pointer查找紀(jì)錄。



您可能還有疑問:如果表建立了聚集索引,每個(gè)數(shù)據(jù)行也要占用9byte嗎
是這樣的。雖然聚集索引的更新操作有所不同,但是為了方便b-tree轉(zhuǎn)換成heap,也需要保持9個(gè)byte



http://www.cnblogs.com/stswordman/archive/2007/08/22/865425.html

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

SQLSERVER中數(shù)據(jù)行所占用的最小空間

SQLSERVER中數(shù)據(jù)行所占用的最小空間:數(shù)據(jù)行所占的最小空間是多少呢? 先來看看下面這張經(jīng)典數(shù)據(jù)行結(jié)構(gòu)圖(引自Inside Sql Server) 因?yàn)榭勺冮L(zhǎng)度類型的列會(huì)有額外的空間開銷,所以不考慮可變長(zhǎng)度的字段。 現(xiàn)在計(jì)算一下除去實(shí)際數(shù)據(jù)后每個(gè)數(shù)據(jù)行所需要占用的空間: 狀態(tài)位A占一個(gè)字節(jié),狀態(tài)位B占
推薦度:
標(biāo)簽: 空間 數(shù)據(jù) 用的
  • 熱門焦點(diǎn)

最新推薦

猜你喜歡

熱門推薦

專題
Top