如何判斷SQL Server BIT類型占用空間的多少?
此文章主要向大家探討的是SQL Server BIT類型占用空間的多少,對于一般的INT、CHAR、tinyint等相關(guān)的數(shù)據(jù)類型,他們所占用的存儲空間都是以Byte字節(jié)為單位的,但是BIT類型由于只有0和1或者說false和true。
這種情況只需要一個Bit位就可以表示了,那么在SQL Server中BIT類型到底占用了多少空間?是不是由一個Bit位來存儲的?或者可能是使用一個字節(jié)來存儲的?
這兩個答案都不正確!實際上BIT類型占用的空間與BIT類型的列所在表的位置有關(guān),有些情況下BIT占用了一個字節(jié),有些情況下BIT實際占用了幾個位(幾個BIT類型的列共用一個字節(jié))。下面就來具體分析一下:
1. 單獨的BIT類型的列將占用一個字節(jié)。
所謂單獨就是指一個BIT類型的列的左邊定長列和右邊定長列都不是SQL Server BIT類型的列。例如這樣一個表:
- CREATE TABLE tt
- (
- c1 INT PRIMARY KEY,
- c2 BIT NOT NULL,
- c3 CHAR(2) NOT NULL
- )
SQL Server在存儲表中的數(shù)據(jù)時先是將表中的列按照原有順序分為定長和變長(變長就是長度不固定的數(shù)據(jù)類型,如varchar,nvarchar,varbinary等)兩組。在數(shù)據(jù)頁中存儲數(shù)據(jù)時先存儲所有定長的數(shù)據(jù),然后再存儲變長的數(shù)據(jù)。這里由于c2列的左邊是int類型,右邊是char類型,都是定長的,而且不是BIT類型,所以c1和c3之間必須留出一個字節(jié)來存儲c2,雖然c2只用到了其中的一個位。
下面我們來驗證一下是否真是如我所說:
(1)插入一行數(shù)據(jù):
- INSERT INTO tt VALUES(1,1,'aa')
(2)找到tt表數(shù)據(jù)的***頁(也就是剛才插入的這行數(shù)據(jù)所在頁)的文件號和頁面號:
- SELECT first_page
- FROM sys.partitions p
- INNER JOIN sys.system_internals_allocation_units a
- ON p.partition_id=a.container_id
- WHERE OBJECT_IDOBJECT_ID= OBJECT_ID('dbo.tt')
我這里返回的是0x76 00 00 00 01 00,這里需要反轉(zhuǎn)過來看0x00 01 00 00 00 76。其中前兩個字節(jié)是文件號,后面的是頁面號,所以文件號是1,頁面號是118(0x76轉(zhuǎn)換成十進(jìn)制就是118)
(3)使用DBCC page命令查看該頁的內(nèi)部結(jié)構(gòu):
- DBCC traceon(3604)
- DBCC page(TestDB,1,118,3)
這兒DBCC traceon(3604)表示將頁面內(nèi)容直接輸出,TestDB是我創(chuàng)建的tt表所在的數(shù)據(jù)庫,1和118前面已經(jīng)說了。***一個是打印選項。0表示只輸出頁頭;1則不會輸出所有內(nèi)容,只是輸出有數(shù)據(jù)的內(nèi)容;2表示完整的輸出這個頁的內(nèi)容,3則和1差不多,但是要每條記錄分別列出列的值。以下是輸出的需要關(guān)注的內(nèi)容:
- 00000000: 10000b00 01000000 01616103 0000††††††.........aa...
關(guān)于數(shù)據(jù)行的具體格式我就不在這里多說了,在《SQL Server 2005技術(shù)內(nèi)幕 存儲引擎》中有詳細(xì)介紹。我們插入的數(shù)據(jù)從第5個字節(jié)開始,是01000000 016161。這兒01000000就是c1,由于是int類型,所以占用4個字節(jié)。接下來01就是c2,在這里占用了1字節(jié)。再接下來6161就是c3了。
2.多個BIT類型的列之間使用變長數(shù)據(jù)類型列分開
則去掉變長列,然后看連續(xù)的SQL Server BIT類型列的個數(shù),每列占用一個位,如果多余了8列那就再占用更多的字節(jié)。例如創(chuàng)建這樣的表:
- CREATE TABLE vtt
- (
- c1 BIT NOT NULL,
- c2 VARCHAR(5) NOT NULL,
- c3 BIT NOT NULL,
- c4 NVARCHAR(5) NULL,
- c5 BIT NULL,
- c6 INT NOT NULL
- )
這里將變長列篩選出來后就變成了c1、c3、c5、c6,有3個BIT類型列是連續(xù)的,所以c1、c3、c5將公用一個字節(jié)。接下來就來驗證一下:
(1)插入一條示例數(shù)據(jù):
- INSERT INTO vtt VALUES(1,'abc',1,N'xyz',0,1023)
(2)用前面用的SQL語句,同樣的方法,找出vtt表的***頁為:0xC00000000100,對應(yīng)的就是文件號1,頁號192
(3)查看該頁的內(nèi)部數(shù)據(jù):
- 00000000: 30000900 03ff0300 00060000 02001500 †0. .............
- 00000010: 1b006162 63780079 007a00†††††††††††††..abcx.y.z.
插入的數(shù)據(jù)從第5個字節(jié)開始03ff…… 這兒03就是c1、c3、c5的數(shù)據(jù),03轉(zhuǎn)換成二進(jìn)制就是00000011。c1列對應(yīng)***位1,c3對應(yīng)倒數(shù)第二位1,c5對應(yīng)倒數(shù)第三位0。接下來的ff就是c6的值1023。后面的就是列數(shù)、NULL位圖、變長列等,這里是討論BIT位占用空間的,所以就不講解后面這些了。
3.一個表中有多個SQL Server BIT類型的列
其順序是否連續(xù)決定了BIT位是否可以共享一個字節(jié)。SQL Server中按照列順序存儲,***列和***一列都是BIT數(shù)據(jù)類型列,不可以共用一個字節(jié)。
也就是說下面的表t1和表t2占用的空間是不同的,t1數(shù)據(jù)占用了7字節(jié),t2數(shù)據(jù)占用了8字節(jié)。
- CREATE TABLE t1
- (
- c1 INT PRIMARY KEY,
- c2 BIT NOT NULL,
- c3 BIT NOT NULL,
- c4 CHAR(2) NOT NULL
- )
- CREATE TABLE t2
- (
- c1 INT PRIMARY KEY,
- c2 BIT NOT NULL,
- c4 CHAR(2) NOT NULL,
- c3 BIT NOT NULL
- )
但是在下面的t3和t4表中,由于中間是變長數(shù)據(jù)類型,所以他們的BIT列占用的數(shù)據(jù)空間是相同的。
- CREATE TABLE t3
- (
- c1 INT NOT NULL,
- c2 BIT NOT NULL,
- c3 VARCHAR(2) NOT NULL,
- c4 BIT NOT NULL
- )
- CREATE TABLE t4
- (
- c1 INT NOT NULL,
- c2 BIT NOT NULL,
- c4 BIT NOT NULL,
- c3 VARCHAR(2) NOT NULL
- )
以上的相關(guān)內(nèi)容就是對SQL Server BIT類型到底占用了多少空間的介紹,望你能有所收獲。
【編輯推薦】