SQLSERVER NULL과 빈 문자열의 차이는 NULL은 공간을 절약하기 위해 사용되는 경우

유형은 여기에만 문자열, INT는, 날짜가 텍스트 데이터 유형은 논의되지 공간 저장 데이터 유형이 지정되어 있기 때문에할지 여부를 논의

이 기사를 쓰기 전에, 나는 항상 읽고, 읽고, 몇 번을 수정 한 후이 문제가 라인에 데이터 페이지에서 보면 매우 간단하다고 생각하지만, 한

읽기 계속하기 전에 데이터 페이지는 SQLSERVER 내부 공간을 알 수 있습니다 전에 잘 알고 SQSERVER에 다음과 같은 글을보고 무엇을, 나는 희망에 의해 점령 필요 찾기

당신이 읽기 전에 다음 문서에서 찾아보세요

의 문자 NCHAR VARCHAR NVARCHAR 구분   : 문자 NCHAR VARCHAR NVARCHAR 길이는 데이터 유형에 의해 점령

중국의 SQL 서버의 물리적 메모리 페이지 은행

SQL 서버 오류 (30)는 -Day6- NULL 비트 맵 세 가지 오류에 대해 이야기하기

표 SQL Server2008의 힙 저장 구조, 오버 플로우 라인

비트 맵에서 NULL SQLSERVER 역할

당신이 너무 오래 기사의 길이를 위해 단지 단지 지식의 겉 핥기 될 수있다 시작하는 사람들을 위해 위의 문서를 참조하지 않는 경우에, 나는 문서의 몇 가지 중요한 용어를 설명하지 않습니다

이 O (∩_∩) O 주어진 글 봐


먼저 다음 표를 작성하고 테스트 데이터를 삽입

  코드보기

 

하는 DBCCResult 테이블을 설정 DBCC IND 결과 저장

  코드보기

 


각각의 경우에보기 테이블

 

상황의 VARCHAR 유형

testnullvarchar 表

  코드보기

데이터 페이지

  코드보기

 

코드를 복사
1 개 슬롯 0 오프셋 0x60으로 길이 (11) 
 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 오프셋 17 0x6b 길이 
14 
15 기록 타입 = PRIMARY_RECORD 기록 속성 = NULL_BITMAP VARIABLE_COLUMNS 
16 
17 메모리 덤프 @ 0x0A16C06B 
18  
19 00000000 : 30000800 02000000 0200fc01 001100c4 † 0 ...............         
20 00000010 : E3 †††††††††††††††††††††††††††††††††††.                        
(21)
22 슬롯 1 열 0 오프셋을 0x4 길이 4 
23 
24 식 (2)                                
25 
26 슬롯 1 열 1 오프셋 0xF입니다 길이 2 
27 
28 NAME =你                            
코드를 복사

우리는 어떻게 나가 11의 기록 길이의 첫 번째 줄에 보면

에서는 SQL 서버 페이지 BOC 물리적 스토리지 데이터 행의 각 세그먼트에서 설명

(2) 상기 상태 A와 상태 B의 -byte 광고 헤더 정보를 저장 (2 행 헤더 바이트)

2 -byte 고정 길이 저장소 크기, 데이터 형식의 행이 고정되지 VARCHAR로 길이 (고정 길이의 길이가 2 바이트 열)

SQLSERVER 필요가 INT를 알고, 고정 길이 크기의 날짜, 소수점 데이터 유형

바이트 시리즈, 행 번호 저장하기위한 테이블 (2 열 수 바이트 테이블) 전체

1 바이트의 널 (null) 비트 맵 (널에 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

필드 저장은 첫 번째 행 레코드 VARCHAR 케이스의 이름, testnotnullvarchar 테이블 및 테이블의 NULL이다 testnullvarchar

이상한 것은 testnotnullvarchar 테이블에 NULL 값을 반환하지 않습니다,하지만 빈 문자열

요약 :

문자 데이터 유형의 경우, 빈 문자열 또는 NULL 값인지 지정된 문자 데이터 형식의 크기가 점유 할 때 테이블을 구축 할 수있는 공간의 크기에 따라 공간입니다

예를 들면 :

1-- 있도록 공기 CHAR 타입 
(가) TABLE을 만들 testnullchar 2합니다 (INT ID, NAME CHAR (20가) NULL) 
. 3 GO

숯은 20, 다음 공간의 20 바이트를 차지

 


개요

VARCHAR 데이터 유형의 경우, 빈 문자열 여부를 NULL 값은 공간을 차지하지 않습니다

문자 데이터 유형의 경우, 빈 문자열 또는 NULL 값인지 지정된 문자 데이터 형식의 크기가 점유 할 때 테이블을 구축 할 수있는 공간의 크기에 따라 공간입니다

 

보기의 위의 실험적인 관점에서, 공간 절약이 결정 여부를 데이터 종류에 따라하는 것은 NULL 또는 빈 문자열 경우입니다

별도로 데이터의 유형을두면, 감 시간 데이터 형식 열 충전 NULL 값과 VARCHAR 데이터 형식 열 충전 NULL 값으로, 비교할 수없는

두 NULL 값은 더 큰 무엇입니까? 유형을 개별적으로 분석 하였다 두 데이터가 두 NULL 값을 비교하지 않고,이 비교는 의미가 없습니다

두 데이터 유형, 유형 날짜를 아무 없었기 때문에뿐만 아니라, VARCHAR 타입이 같지 않은

동일 문자와 VARCHAR의 사실이다

비교는 단지 빈 문자열과 NULL 값을 비교하는 VARCHAR 데이터 유형이다, 데이터 유형 의미가 있습니다

CHAR 데이터 유형은 같은 빈 문자열, 그리고 NULL 값을 비교한다

그래서 보통은 SQLSERVER 데이터 유형의 특정 이해가 테이블 스페이스 시스템의 사용의 대략적인 파악을 위해 할

 

잘못된 장소 경우, Paizhuan O (∩_∩) O를 환영합니다

추천

출처www.cnblogs.com/ljs-13/p/12163360.html