數據類型在精度,範圍上有較大的差別。選擇合適的類型可以減少table和index的大小,進而減少IO的開銷,提高效率。本文介紹基本的數值類型及其之間的細小差別。
最常用的數值類型是int,但是它未必是最佳選擇。bigint,smallint,tinyint可以應用在特殊場合。他們的特性如下表所示:
Data type | Range | Storage |
---|---|---|
bigint |
-2^63 (-9,223,372,036,854,775,808) to 2^63-1 (9,223,372,036,854,775,807) |
8 Bytes |
int |
-2^31 (-2,147,483,648) to 2^31-1 (2,147,483,647) |
4 Bytes |
smallint |
-2^15 (-32,768) to 2^15-1 (32,767) |
2 Bytes |
tinyint |
0 to 255 |
1 Byte |
可見如果某一列的值只有10來個值,而你卻用了int,那麼沒行數據多佔用了3個字節。如果有1G的行數,那麼你多用了3G的空間。如果它還在index中,ok,它又佔用了不必要的3G。
與此類似的是Float和Real,他們的格式如下:
Data type | Range | Storage |
---|---|---|
float |
- 1.79E+308 to -2.23E-308, 0 and 2.23E-308 to 1.79E+308 |
Depends on the value of n 1,24=4 bytes 25,53=8bytes |
real |
- 3.40E + 38 to -1.18E - 38, 0 and 1.18E - 38 to 3.40E + 38 |
4 Bytes |
需要說明的是,float的長度取決於一個參數,雖然我們通常聲明的時候並不指定float的長度,實際上是存在這樣的選項的。這個長度默認是53,數值範圍如上表所示。
顯然如果你要表示的數字不會超過10的38次方的話,你應該用real,他可以爲你節省4個字節。
另一個相關的例子是decimal和numerical,他們是另一組精確表示數值的類型。float和real是不精確的,所以不能做相等的比較。
decimal和float在功能是等價的,爲什麼要分成兩個名字,我也不清楚。
decimal的聲明如下:decimal(p,s),p表示總共多少位,包括小數點前後的數字,s表示小數點後多少位,p不能超過38,當然s不能超過p,缺省是0。
decimal的範圍是正負10的p-s次方的結果 減去10的-s次方。比如decimal(2,1)的範圍是正負9.9。
decimal的長度和p的大小相關,如下表所示:
Precision | Storage bytes |
---|---|
1 - 9 |
5 |
10-19 |
9 |
20-28 |
13 |
29-38 |
17 |
可使用變長字節來存放decimal。此時數據庫根據實際數值的大小來存放decimal,而不是根據聲明來判斷。如果表中沒有var length的列,那麼需要額外的兩個字節,否則不會有額外的需要。
可以通過如下的命令啓動一個數據庫上的變長decimal存儲:
EXEC sp_db_vardecimal_storage_format 'AdventureWorks', 'ON' ;
通過EXEC sp_db_vardecimal_storage_format ;查看所有啓動了這一功能的數據庫。
通過EXEC sp_tableoption 'Sales.SalesOrderDetail', 'vardecimal storage format', 1 ;
啓動對某個表的變長decimal存儲。
最後再看看datetime和smalldatetime,兩者都表示時間,區別如下:
datetime表達的時間更久,1753到9999,精度更高,300分之一秒,佔用8個字節;
smalldatetime表達的時間較短,1900到2079,精確到分,4個字節。
通常情況下,smalldatetime是夠用的。