1、MySQL數據類型選擇原則
更小的一般更好:通常狀況下選擇能夠正確存儲數據的最小數據類型。越小的數據類型一般更快,佔用磁盤,內存和CPU緩存更小。算法
簡單就好:簡單的數據類型的操做一般須要更少的CPU週期。例如:整型比字符操做代價要小得多,由於字符集和校對規則(排序規則)使字符比整型比較更加複雜。sql
儘可能避免NULL:儘可能制定列爲NOT NULL,除非真的須要NULL類型的值。由於可能爲NULL列使得索引,索引統計和值比較都更復雜。可爲NULL的列會使用更多的存儲空間,在MySQL裏也須要特殊處理。數據庫
2、選擇具體數據類型
在選擇列的數據類型時須要先選定合適的大類型,如:數字,字符串,時間等。編程
(1)、整數類型緩存
數據類型 |
長度/字節 |
範圍 |
TINYINT |
1 |
-2^7—2^7-1 |
SMALLINT |
2 |
-2^15—2^15-1 |
MEDIUMINT |
3 |
-2^23—2^23-1 |
INT |
4 |
-2^31—2^31-1 |
BIGINT |
8 |
-2^64—2^64-1 |
區分開TINYINT / INT / BIGINT,能肯定不會使用負數的字段,建議添加 unsigned定義。服務器
可以用數字類型的字段儘可能選擇數字類型而不用字符串類型。編程語言
(2)、實數類型函數
實數是帶有小數部分的數字。然而它們不僅是存儲小數部分;也能夠是DECIMAL存儲比BIGINT還大的整數。MYSQL即支持精確類型,也支持非精確存儲。FLOAT和DOUBLE類型支持使用標準的浮點運算進行近似計算。具體計算規則取決於所使用平臺的實現。post
數據類型 |
長度/字節 |
範圍 |
FLOAT |
4 |
— |
DOUBLE |
8 |
— |
DECIMAL |
最多65數字(5.0以上版本) |
— |
MySQL使用DOUBLE做爲內部浮點計算的類型。注意,DECIMAL須要額外的空間和計算開銷,因此只要要求儘可能對小數進行精確時才使用DECIMAL,例如在存儲財務數據時,能夠用BIGINT來替代它來實現,只須要將數據乘以相應的倍數便可。性能
FLOAT和DOUBLE選擇(儘可能選擇FLOAT)
如何有涉及到運算,用float和double可能會精度不許,能夠考慮將小數乘於相應的倍數,而後用BIGINT來存儲。
(3)、字符串類型
MySQL支持多種字符串類型。從4.1版本開始,每一個字符串列能夠定義本身的字符集和校對規則(排序規則),這些東西會在很大程度上影響性能。
一、VARCHAR和CHAR類型
VARCHAR和CHAR時最主要的兩種字符串類型。
VARCHAR:適用於存儲變長的字符串,是最多見的字符串數據類型。它比定長更加節省空間,由於它僅須要使用必要的額外空間(若是MySQL表使用ROW_FORMAT=FIXED建立的話,會使用定長)。
適合使用該類型的狀況:字符串列的最大長度比平均長度大不少;列的更新不多,因此碎片不是問題;使用了UTF-8這樣複雜的字符集,每一個字符的使用不一樣字節數進行存儲。
注:5.0以上版本會保留末尾空格,更早的版本會刪除末尾空格。InnoDB存儲引擎會把過長的VARCHAR轉換爲BLOB類型。
CHAR:CHAR是定長字符串類型,MySQL老是根據定義的類型進行分配足夠的空間。當存儲CHAR時MySQL會默認刪除行尾空格。由於CHAR值一般須要用空格進行填充以方便比較。
CHAR適合存儲很短的字符串,或者全部長度都接近一個長度。
對於常常變動的數據CHAR比較VARCHAR要好,由於定長的CHAR類型不容易產生碎片。
對於更短的列CHAR比VARCHAR要更加節省空間,由於VARCHAR老是須要一個額外的字節來存儲長度。
二、BLOB和TEXT類型
BLOB和TEXT是用來存儲很大的數據來設計的字符串數據類型,分別採用二進制和字符方式進行存儲。
實際上他們時屬於兩種不一樣數據類型家族:字符類型的時TINYTEXT, SMALLTEXT, TEXT, MEDIUMTEXT, LONGTEXT;對應的二進制類型是TINYBLOB, SMALLBLOB, BLOB, MEDIUMBLOB, LONGBLOB。
BLOB和TEXT的僅有的區別在於BLOB類型存儲的時二進制數據,沒有排序規則或字符集,而TEXT類型有字符集和排序規則。
char,varchar,TEXT的選擇:非萬不得已不要使用 TEXT 數據類型,定長字段,建議使用 CHAR 類型(填空格),不定長字段儘可能使用 VARCHAR(自動適應長度,超過階段),且僅僅設定適當的最大長度。
(4)、日期和時間類型
MySQL可使用不少類型來保存日期和時間值,例如YEAR和DATE.MySQL能存儲最小粒度爲秒。可是可使用微秒級的力度進行運算。
一、DATETIME
能保存1001到9999年,精度爲秒。格式爲YYYY-MM-DD HH:MM:SS與時區無關,使用八個字節的存儲空間。
二、TIMESTAMP
時間戳,正如名字同樣。它能保存從1970年1月1號午夜(格林尼治標準時間)。它只使用四個字節的存儲空間只能表示1970到2038年。
TIMESTAMP顯示的值依賴於時區。MYSQL服務器,操做系統,以及客戶端鏈接都有時區設置。所以存儲值爲0時在不一樣的時區顯示值會有差異。
注:一般狀況下應儘可能使用TIMESTAMP,由於它比DATETIME效率更高。若是須要存儲更小粒度的時間,能夠用BIGINGT或者轉換成DOUBLE類型來進行存儲。
(5)、ENUM數據類型
枚舉數據類型在內存中很是緊湊,會根據列表值的數量壓縮到一個或兩個字節。MySQL自身會維護一個查找表。例如:
CREATE TABLE enum_test(
`gender` ENUM("男","女","其餘") NOT NULL
);
INSERT INTO enum_test values("男"),("女"),("其餘");
對於狀態字段,能夠嘗試使用 ENUM 來存放。
避免使用NULL字段,很難查詢優化且佔用額外索引空間。
****************************************************華麗的分割線**************************************************************
一。char和varchar
char是固定長度的,查詢速度比varchar速度快的多。char的缺點是浪費存儲空間。
檢索char列時,返回的結果會刪除尾部空格,因此程序須要對爲空格進行處理。
對於長度變化不大且對查詢速度有較高要求的數據能夠考慮使用char。
隨着MySQL的不斷升級,varchar的性能不斷改進並提升。
存儲引擎使用原則:
MyISAM:建議使用固定長度列代替可變長度列。
InnoDB:建議使用varchar類型
二。text和blob
在保存大文本時,一般選擇text或者blob。
兩者的差異是blob能夠保存二進制數據,好比照片。
text和blob又包括text、mediumtext、longtext和blob、mediumblob、longblob,他們之間的區別是存儲文本長度不一樣和存儲字節不一樣。
應根據狀況選擇知足需求的最小存儲類型。
1.blob和text執行大量刪除操做時,產生數據「空洞」
![](http://static.javashuo.com/static/loading.gif)
刪除id爲7記錄先後數據庫所佔內存,沒有發生變化。
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
能夠發現數據文件並無由於數據刪除而減小。
對錶進行optimize(優化)操做:
![](http://static.javashuo.com/static/loading.gif)
能夠發現表數據文件大大縮小,「空洞」空間已經被回收。
2.用合成(Synthetic)索引提升查詢性能
根據大文本字段(text、blob)的內容創建一個散列值,並把這個值存儲在單獨的數據列中,而後經過散列值找數據行。
缺點:只能進行精確查詢(<、>=範圍操做符是沒有用處的)
能夠經過MySQL自帶函數md5()、sha1()、crc32()生成散列值,也能夠經過編程語言計算散列值。
注:若是散列算法生成的字符串帶有尾部空格,不要把他們存儲在char、varchar列中,他們會受到尾部空格去除的影響。
![](http://static.javashuo.com/static/loading.gif)
若是須要對blob或clob字段進行模糊查詢,能夠用前綴索引:
1
2
3
4
|
#前綴索引:對context字段的前100個字符建立索引
create
index
idx_blob
on
t2(context(100));
#查詢方法
select
*
from
t2
where
context
like
'drake%'
;注:%不能放在最前面
|
合成索引只能用於精確匹配,在必定程度上減小了I/O,從而提升了查詢效率。
3.在沒必要要的時候避免檢索大型的blob或text值。
4.把blob或text列分離到單獨的表中。
3、浮點數和定點數
1.浮點數存在偏差問題。
2.對貨幣等對精度敏感的數據,應該用定點數表示或存儲。
3.在編程中,若是用到浮點數,要特別注意偏差問題,並儘可能避免作浮點數比較。
4.要注意一些特殊值的處理。
4、日期類型的選擇
1.根據實際須要選擇可以知足應用的最小存儲日期類型。
2.若是記錄年月日時分秒,而且記錄年份比較久遠,最好使用datetime,不要使用timestamp。
3.若是記錄的日期須要讓不一樣時區的用戶使用,最好使用timestamp,由於日期類型中只有它可以和實際時區相對應。