SQLSERVER NULLと空の文字列との違いは、NULL、スペースを節約するために使用されている場合

データ型が指定されているため、タイプは、スペースを節約するかどうかを、ここでの唯一の文字列、int型、日時、テキストデータ型で議論されていない議論しました

この記事を書く前に、私はいつも、この問題は非常に単純であることをライン上のデータ・ページを見て思ったが、その後読み、読み、数回変更しています

あなたが読むことを続行する前に、データ・ページを使用すると、SQLSERVER内部スペースを知ることができる前に非常に精通しSQSERVERにあなたは、次の資料を見て何を、私は願っていますによって占められる必要がある検索

あなたが読む前に、以下の記事をご覧ください。

char型nchar型varchar型はnvarcharの区別   :データタイプによって占めchar型nchar型varchar型はnvarcharの長さ

SQL Serverの物理メモリページ中国の銀行

SQL Serverのエラー30は-Day6- NULLビットマップ3つのエラーについて話をします

テーブルSQL Server2008ヒープストレージ構造、オーバーフローライン

ビットマップ内のNULL SQLSERVERの役割

あなたはまだ始まったばかりしている人だけではない、あまりにも長い記事の長さにするために、知識の片言することができるため、上記の記事を、表示されない場合、私は記事のいくつかの重要な用語を説明しています

それはO(∩_∩)O与えられた記事を見てください


まず、次の表を作成し、テストデータを挿入

  コードの表示

 

DBCC IND結果の保存、DBCCResultテーブルを確立

  コードの表示

 


それぞれの場合のビューテーブル

 

状況のVARCHARタイプ

testnullvarchar表

  コードの表示

データページ

  コードの表示

 

コードをコピー
1つのスロット0のオフセット0x60の長さ11 
 2 
 3レコードタイプ= PRIMARY_RECORDレコード= NULL_BITMAP属性      
 0x0A16C060 @ 4メモリダンプ
 5 
 6 00000000:10000800 01000000 0200fe†††††††††††††........ ...               
 7 
 8スロット0列0のオフセットを0x4長さ4 
 9 
10、ID = 1                                
11 NAME = [NULL]                         
12 
13スロット1オフセット0x6b長さ17 
14 
15レコードタイプ= PRIMARY_RECORDレコード= NULL_BITMAP VARIABLE_COLUMNS属性
16 
0x0A16C06B @ 17メモリダンプ
18を
19 00000000:30000800 02000000 0200fc01 001100c4†0 ...............          
20 00000010:E3†††††††††††††††††††††††††††††††††††。                        
21
22スロット1列0のオフセットを0x4長さ4 
23 
24 ID = 2                                
25 
26スロット1列1オフセット0xFの長さ2 
27 
28 NAME =你                            
コードをコピー

私たちはどのように出て11の記録長さの最初の行を見て

ではSQL ServerのページBOC物理ストレージのデータ行の各セグメントはで説明されています

2状態Aと状態B(行ヘッダバイト2)の-byte線ヘッダ情報が格納され

2 -byte固定長ストレージサイズ、データ・タイプの行は、これらが固定されていないVARCHARとして長さ(固定長の長さが2つのバイト列)

SQLSERVERの必要性はint型を知るために、固定長サイズの日時、小数点データ型

二つの一連のバイト、行番号を格納するテーブル(の列数の2つのバイトテーブル) 合計

1バイトのヌルビットマップ、(ヌルのための1バイトのビットマップ)

4データ記憶されているint型のバイト(INT 4バイト(1列目 ))

2 + 2 + 2 + 1 + 4 = 11

つまり、最初の行のレコード名がNULLであるため、最初の行のレコード名フィールドには、任意のスペースを取りません。

-------------------------------------------------------------------------------------------------------

我们看第二行记录长度17怎麽得出来的

2个字节行标头存储了状态A和状态B的信息(2 bytes row header)

2个字节存储固定长度大小,因为一行记录了有varchar这些不固定长度的数据类型(2 bytes for length of fixed length columns)

SQLSERVER需要知道int、datetime、decimal这些固定长度数据类型的大小

2个字节的列数,用来存储这个表一共有多少列(2 bytes for number of columns in the table)

1个字节的null bitmap,(1 byte for null bitmap)

4个字节存储int型数据(4 bytes for int (1st column))

2个字节存储数据行中的可变长度列数量,统计数据行中一共有多少列是nvarchar ,varchar类型的列( 2 bytes for number of variable length columns in the table)

2个字节存储可变长度偏移阵列,可变长度偏移阵列的公式

2*表格中可变长度数据类型的列数量,这个表只有一列varchar,所以2*1=2,为什麽要有可变长度偏移阵列?我估计是因为可变长度的数据类型

存储的数据是不固定的,所以要预留一些位置,当update varchar值的时候有足够的位置(2 bytes for name column offset)

2个字节存储name列的值,为什麽用两个字节大家可以看一下char nchar varchar nvarchar的区别 2 bytes for name (你)

2+2+2+1+4+2+2+2=17

 

前11个字节跟第一行记录是一样的长度,关键在于后面的6个字节,在这6个字节中只有2个字节实际存储数据的

为什麽在第一行记录里没有这4个字节呢?

2个字节存储数据行中的可变长度列数量

2个字节存储可变长度偏移阵列

想法:

我估计是因为,第一行记录中没有一个可变长度数据类型的列是有数据的,全部都是NULL,

既然这样SQLSERVER就没有必要再用4个字节去存储2个字节存储数据行中的可变长度列数量和2个字节存储可变长度偏移阵列

我们来验证一下这个想法:

代码如下:

  View Code

数据页内容

  View Code

我们看第一行记录长度19怎麽得出来的

2个字节行标头存储了状态A和状态B的信息

2个字节存储固定长度大小

2个字节的列数

1个字节的null bitmap

4个字节存储int型数据

2个字节存储数据行中的可变长度列数量

4个字节存储可变长度偏移阵列  2*2=4

2个字节存储name列的值

2+2+2+1+4+2+4+2=19

也就是说,一行记录中全部的可变长度数据列的数据全部为NULL,才不会有这4个字节

2个字节存储数据行中的可变长度列数量

2个字节存储可变长度偏移阵列

 

其实SQLSERVER也做了一下标记,区分开一行记录中全部的可变长度类型列的数据全部为NULL还是一些为NULL一些不为NULL,还是全部不为NULL

这里可以在行记录属性中看出,testnullvarchar表的第一行和第二行

第一行NULL_BITMAP表明一行记录中全部的可变长度类型列的数据全部为NULL

第二行NULL_BITMAP VARIABLE_COLUMNS表明一些为NULL一些不为NULL或者全部不为NULL

小结:

VARCHAR类型NULL值不占用任何空间

 

 

testnotnullvarchar表

  View Code

数据页内容

  View Code
コードをコピー
 1 Slot 0 Offset 0x60 Length 11
 2 
 3 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
 4 Memory Dump @0x0855C060
 5 
 6 00000000:   10000800 01000000 0200fc†††††††††††††...........              
 7 
 8 Slot 0 Column 0 Offset 0x4 Length 4
 9 
10 id = 1                               
11 NAME = [NULL]                        
12 
13 Slot 1 Offset 0x6b Length 17
14 
15 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
16 
17 Memory Dump @0x0855C06B
18 
19 00000000:   30000800 02000000 0200fc01 001100c4 †0...............         
20 00000010:   e3†††††††††††††††††††††††††††††††††††.                        
21 
22 Slot 1 Column 0 Offset 0x4 Length 4
23 
24 id = 2                               
25 
26 Slot 1 Column 1 Offset 0xf Length 2
27 
28 NAME = 你                            
コードをコピー

 

testnotnullvarchar表的数据页和testnullvarchar表的数据页对比一下

看到上面的对比图我也不再对testnotnullvarchar表做详细分析了

情况跟testnullvarchar表是一样的

只有一个地方不一样,就是LEN()函数

 

小结:

对于varchar数据类型,无论是空字符串还是NULL值都不占用任何空间

 


CHAR类型的情况

testnullchar表

  View Code

数据页内容

  View Code
コードをコピー
 1 Slot 0 Offset 0x60 Length 31
 2 
 3 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
 4 Memory Dump @0x0A27C060
 5 
 6 00000000:   10001c00 01000000 00000000 00000000 †................         
 7 00000010:   00000000 00000000 00000000 0200fe††††...............          
 8 
 9 Slot 0 Column 0 Offset 0x4 Length 4
10 
11 id = 1                               
12 NAME = [NULL]                        
13 
14 Slot 1 Offset 0x7f Length 31
15 
16 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
17 Memory Dump @0x0A27C07F
18 
19 00000000:   10001c00 02000000 c4e32020 20202020 †..........               
20 00000010:   20202020 20202020 20202020 0200fc††††            ...          
21 
22 Slot 1 Column 0 Offset 0x4 Length 4
23 
24 id = 2                               
25 
26 Slot 1 Column 1 Offset 0x8 Length 20
27 
28 NAME = 你                            
コードをコピー

 

我们看第一行记录长度31怎麽得出来的

2个字节行标头存储了状态A和状态B的信息(2 bytes row header)

2个字节存储固定长度大小,因为一行记录了有varchar这些不固定长度的数据类型(2 bytes for length of fixed length columns)

4个字节存储int型数据(4 bytes for int (1st column))

2个字节的列数,用来存储这个表一共有多少列(2 bytes for number of columns in the table)

1个字节的null bitmap,(1 byte for null bitmap)

20个字节存储name列的值,为什麽用20个字节大家可以看一下char nchar varchar nvarchar的区别  20 bytes for char(20) (2nd column)

2+2+4+2+1+20=31

换言之,第一行记录中name字段是否为NULL,都占用20个字节的空间

-----------------------------------------------------------------------------------------

我们看第二行记录长度31怎麽得出来的

实际上第二行记录和第一行记录是一样的,只不过第二行记录里的name列存储了实际的值“”,

而不管存储的值大小如何都占用20个字节

2个字节行标头存储了状态A和状态B的信息(2 bytes row header)

2个字节存储固定长度大小,因为一行记录了有varchar这些不固定长度的数据类型(2 bytes for length of fixed length columns)

4个字节存储int型数据(4 bytes for int (1st column))

2个字节的列数,用来存储这个表一共有多少列(2 bytes for number of columns in the table)

1个字节的null bitmap,(1 byte for null bitmap)

20个字节存储name列的值,为什麽用20个字节大家可以看一下char nchar varchar nvarchar的区别 20 bytes for char(20) (2nd column)

2+2+4+2+1+20=31

 

小结:

CHAR类型NULL值会占用空间,所占用空间大小取决于建表时候指定的char数据类型的大小

例如:

1 --允许空,char类型
2 CREATE TABLE testnullchar(id INT,NAME CHAR(20) NULL)
3 GO

指定char为20,那么就占用20个字节的空间

 

testnotnullchar表

  View Code

数据页内容

  View Code
コードをコピー
 1 Slot 0 Offset 0x60 Length 31
 2 
 3 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
 4 Memory Dump @0x0A01C060
 5 
 6 00000000:   10001c00 01000000 20202020 20202020 †........                 
 7 00000010:   20202020 20202020 20202020 0200fc††††            ...          
 8 
 9 Slot 0 Column 0 Offset 0x4 Length 4
10 
11 id = 1                               
12 
13 Slot 0 Column 1 Offset 0x8 Length 20
14 
15 NAME =                               
16 
17 Slot 1 Offset 0x7f Length 31
18 
19 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
20 Memory Dump @0x0A01C07F
21 
22 00000000:   10001c00 02000000 c4e32020 20202020 †..........               
23 00000010:   20202020 20202020 20202020 0200fc††††            ...          
24 
25 Slot 1 Column 0 Offset 0x4 Length 4
26 
27 id = 2                               
28 
29 Slot 1 Column 1 Offset 0x8 Length 20
30 
31 NAME = 你                            
コードをコピー

 testnotnullchar表的数据页和testnullchar表的数据页对比一下

 

看到上面的对比图我也不再对testnotnullchar表做详细分析了

情况跟testnullchar表是一样的

只有两个地方不一样,testnotnullchar表的第一行记录的name字段存储的是空字符串

而testnullchar表的第一行记录的name字段存储的是NULL

不过无论是空字符串还是NULL都占用了31个字节

LEN()函数返回的值不一样,这里跟varchar类型的情况也是一样的

varchar类型不一样的是,testnotnullchar表的第一行记录的name字段存储的是空字符串,而testnullchar表的第一行记录的name字段存储的是NULL

フィールド格納する第1行レコードVARCHARの場合、testnotnullvarcharテーブルとテーブルの名前がNULL testnullvarcharあります

奇妙なことは、testnotnullvarcharテーブルがNULL値を返すことはありませんが、空の文字列

要約:

CHARデータ型のために、それは空の文字列またはNULL値であるか否かを指定した文字データ型のサイズが占有するときのテーブルを構築するための空間の大きさに応じて、空間であります

例えば:

1--可能空気、char型
CREATE TABLEをtestnullchar 2(INT ID、NAME CHAR(20)とNULL)
。3 GO

charが20で、その後、スペースの20バイトを取ります

 


概要

それは、空の文字列またはNULL値であるかどうか、varcharデータ型のための任意のスペースを取りません。

CHARデータ型のために、それは空の文字列またはNULL値であるか否かを指定した文字データ型のサイズが占有するときのテーブルを構築するための空間の大きさに応じて、空間であります

 

ビューの上記の実験点から、省スペース化がデータタイプに応じて決定されているか否かをNULLまたは空の文字列でない場合

別にデータの種類を残して、センスDATETIMEデータ型カラム充填されたNULL値とVARCHARデータ型カラム充填されたNULL値として、比較することはできません

大きい二つのNULL値、?種類を個別に分析した二つのデータは、これら2つのNULL値を比較せずに、この比較は意味がありません。

2つのデータ型は、datetime型を何の関係もなかったので、しかしまた、varchar型のタイプが等しくありません

同じは、charとvarcharの真実であります

唯一の空の文字列とNULL値を比較して、varcharデータ型と同じように、データ型に理にかなって比較

CHARデータ型は、同じ空の文字列であり、NULL値が比較されます

だから、通常、あなたは、テーブルスペースシステムの使用の大まかな把握しているために、SQLSERVERデータ型の一定の理解を持っていると思います

 

間違った場所ならば、Paizhuan O(∩_∩)O歓迎

おすすめ

転載: www.cnblogs.com/ljs-13/p/12163360.html