[SQL SERVER][Performance]重視 Null 值 (1)

[SQL SERVER][Performance]重視 Null 值 (1)

Null 值表示未知(UnKnown)而不是沒有(Nothing),所以兩個 Null 永遠不會相等,

使用 Null 值會增加 SQL Server Storage Engine(儲存引擎)複雜性,

以及應用程式邏輯判斷複雜性(意外bug可能變多),

所以在建立資料表的同時,我個人認為 Null 值應該盡量減少使用,

並且明確指定 not null and default values。

 

1.Null 值會增加SQL Server Storage Engine複雜性

因為SQL Server會在每一列使用一個特殊的bitmap來表示該欄位是否允許 Null,

如果 Null 被允許的話,那麼每查詢一列資料時,SQL Server必須解碼這個bitmap。

 

2.增加應用程式邏輯判斷複雜性

因為兩個 Null 永遠不會相等,且邏輯與比較運算子可能會傳回第三種結果 UNKNOWN,

同時某些計算(如取平均值或加總)也不會包含 Null,這些小地方都將導致運算結果不正確。

 

下面我們實際來測試看看 Null 帶來的一些問題。

1.效能問題(分別測試新增資料和查詢排序)

新增 Null 資料

--建立資料表(testnull)
create table testnull
(
c1 int ,
c2 varchar(10)
)
--新增資料
set nocount on
declare @step int=1
while(@step <=50000)
begin
    insert into testnull values(null,'rico'+ CAST(@step as varchar(10))) 
    set @step=@step+1
end
go

 

image

總執行時間(ms):22265。

 

查詢排序 Null 欄位

select * from testnull
order by c1 desc  

image

總執行時間(ms):843。

 

新增 Not Null 資料

--建立資料表(testnotnull)
create table testnotnull
(
c1 int not null default 0,
c2 varchar(10) not null 
)
--新增資料
set nocount on
declare @step int=1
while(@step <=50000)
begin
    insert into testnotnull values(default,'rico'+ CAST(@step as varchar(10))) 
    set @step=@step+1
end
go

 

 

image

總執行時間(ms):21531。

 

查詢排序 Not Null 欄位

select * from testnotnull
order by c1 desc  

image

總執行時間(ms):140。

 

可以看到新增  Null 資料以及查詢排序大部分 Null 資料時整體效能都不及Not Null的處理。

 

 

2.增加邏輯判斷複雜性

select 'rico'+null
select 1+null

 

image

 

if null=null
 print 'null相等'
else
 print 'null不相等'

image

 

由於沒有判斷 isnull 將導致結果不如預期。

 

 

結論

當在設計資料表時,請好好重視 Null 值所帶來的影響,

如上面我幾個簡單的效能測試,以及應用程式邏輯判斷上的處理成本增加,

如果可以的話,請儘可能明確使用 Not Null 並同時指定預設值,

但如果你真的需要使用 Null 值,SQL2008 新增了疏鬆資料行來最佳化儲存 Null 值的一般資料行,

可是需要付出擷取非 Null 值的更多成本負擔,

所以當空間至少節省了 20% ~ 40% 時,就可以考慮使用疏鬆資料行。

下一篇我們再來談談資料庫 Null 相關選項特性。

 

 

參考

使用疏鬆資料行

Null 值