簡介
一些資料存儲的基礎知識
在sql server中,資料的存儲以頁為機關。八個頁為一個區。一頁為8k,一個區為64k,這個意味着1m的空間可以容納16個區。如圖1所示:
圖1.sql server中的頁和區
如圖1(ps:發現用windows自帶的畫圖程式畫部落格中的圖檔也不錯)可以看出,sql server中的配置設定單元分為三種,分别為存儲行内資料的in_row_data,存儲lob對象的lob_data,存儲溢出資料的row_overflow_data。下面我們通過一個更具體的例子來了解這三種配置設定單元。
我建立如圖2所示的表。
圖2.測試表
圖3.超過8060位元組的行所配置設定的頁
資料類型的選擇
在了解了一些基礎知識之後。我們知道sql server讀取資料是以頁為機關,更少的頁不僅僅意味着更少的io,還有更少的記憶體和cpu資源消耗。是以對于資料選擇的主旨是:
盡量使得每行的大小更小
這個聽起來非常簡單,但實際上還需要對sql server的資料類型有更多的了解。
比如存儲int類型的資料,按照業務規則,能用int就不用bigint,能用smallint就不用int,能用tinyint就不用smallint。
是以為了使每行的資料更小,則使用占位元組最小的資料類型。
1、比如不要使用datetime類型,而根據業務使用更精确的類型,如下表:
2、使用varchar(max),nvarchar(max),varbinary(max)來代替text,ntext和image類型
根據前面的基礎知識可以知道,對于text,ntext和image類型來說,每一列隻要不為null,即使占用很小的資料,也需要額外配置設定一個lob頁,這無疑占用了更多的頁。而對于varchar(max)等資料類型來說,當資料量很小的時候,存在in-row-data中就能滿足要求,而不用額外的lob頁,隻有當資料溢出時,才會額外配置設定lob頁,除此之外,varchar(max)等類型支援字元串操作函數比如:
● col_length
● charindex
● patindex
● len
● datalength
● substring
3、對于僅僅存儲數字的列,使用數字類型而不是varchar等。
因為數字類型占用更小的存儲空間。比如存儲123456789使用int類型隻需要4個位元組,而使用varchar就需要9個位元組(這還不包括varchar還需要占用4個位元組記錄長度)。
4、如果沒有必要,不要使用nvarchar,nchar等以“字”為機關存儲的資料類型。這類資料類型相比varchar或是char需要更多的存儲空間。
5、關于char和varchar的選擇
這類比較其實有一些了。如果懶得記憶,大多數情況下使用varchar都是正确的選擇。我們知道varchar所占用的存儲空間由其存儲的内容決定,而char所占用的存儲空間由定義其的長度決定。是以char的長度無論存儲多少資料,都會占用其定義的空間。是以如果列存儲着像郵政編碼這樣的固定長度的資料,選擇char吧,否則選擇varchar會比較好。除此之外,varchar相比char要多占用幾個位元組存儲其長度,下面我們來做個簡單的實驗。
首先我們建立表,這個表中隻有兩個列,一個int類型的列,另一個類型定義為char(5),向其中插入兩條測試資料,然後通過dbcc page來檢視其頁内結構,如圖4所示。
圖4.使用char(5)類型,每行所占的空間為16位元組
下面我們再來看改為varchar(5),此時的頁資訊,如圖5所示。
圖5.varchar(5),每行所占用的空間為20位元組
是以可以看出,varchar需要額外4個位元組來記錄其内容長度。是以,當實際列存儲的内容長度小于5位元組時,使用char而不是varchar會更節省空間。
關于null的使用
關于null的使用也是略有争議。有些人建議不要允許null,全部設定成not null+default。這樣做是由于sql server比較時就不會使用三值邏輯(true,false,unknown),而使用二值邏輯(true,false),并且查詢的時候也不再需要isnull函數來替換null值。
但這也引出了一些問題,比如聚合函數的時候,null值是不參與運算的,而使用not null+default這個值就需要做排除處理。
是以null的使用還需要按照具體的業務來看。
考慮使用稀疏列(sparse)
稀疏列是對 null 值采用優化的存儲方式的普通列。 稀疏列減少了 null 值的空間需求,但代價是檢索非 null 值的開銷增加。 當至少能夠節省 20% 到 40% 的空間時,才應考慮使用稀疏列。
稀疏列在ssms中的設定如圖6所示。
圖6.稀疏列
對于主鍵的選擇
總結
本篇文章對于設計表時,資料列的選擇進行了一些探尋。好的表設計不僅僅是能滿足業務需求,還能夠滿足對性能的優化。
====================================分割線================================
最新内容請見作者的github頁:http://qaseven.github.io/