通常狀況下,應該儘可能使用能夠正確存儲數據的最小數據類型,好比只需存儲0--200的整數,則使用 tinyint unsigned 會比 int 好。更小的數據類型一般更快,由於它們佔用更小的磁盤、內存和CPU緩存,而且處理時須要的CPU週期也更少。所以在選擇的時候應該選擇你認爲不會超出範圍的最小數據類型。緩存
簡單數據類型的操做一般狀況下須要的CPU週期更小。好比,整型比字符串操做代價更低,由於字符集和校對規則使得字符的比較比整型比較更加的複雜(如:存儲時間一般使用date、time、datetime 比 使用字符串存儲性能更好)。服務器
在設計表結構時,最好指定列爲NOT NUll,除非真正的須要存儲NULL值。數據結構
解釋:若是在查詢的時候包含有NULL的列,對於MYSQL來講更加的難以優化,由於能夠爲NULL的列使得索引、索引統計和值比較都很是的複雜。可爲NULL的列會使用更多的存儲空間,在MYSQL裏面也須要特殊的處理。當能夠爲NULL的列被索引時,每一個索引記錄須要一個額外的字節,在MyISAM裏甚至還可能致使固定大小的索引變爲可更改大小的索引(意味着性能受到影響)併發
tinyint(8位)、smallint(16位)、mediumint(24位)、int(32位)、bigint(64位)函數
整形類型有可選擇的unsigned的屬性,若是不須要負數,則使用unsigned會使得存儲正數的範圍提升到一倍,好比tinyint存儲範圍爲-128---127,使用tinyint unsigned存儲的範圍變爲0---255。工具
MySQL能夠爲整數類型指定寬度例如:int(11),可是對於大多數應用這是沒有意義的:由於它不會限制值得合法範圍,只是規定了MySQL的一些交互工具用來顯示字符的個數,對於存儲和計算來講,int(11)跟int(20)沒有任何的區別。性能
可使用decimal存儲比bigint還大的整數,decimal用來存儲精確的小數,在MySQL5.0以上的版本中decimal還支持高精度的計算。decimal能夠指定小數點先後所容許的最大位數,MySQL會將數字打包存儲在一個二進制的字符串中。浮點類型在存儲一樣範圍的值時,一般比decimal使用更少的空間。優化
選擇:由於須要額外的空間計算和開銷,因此應該儘可能只在對小數進行計算的時候才使用decimal----涉及到財務計算類的業務。可是在數據量比較大的時候能夠考慮使用bigint代替decimal,將須要存儲的貨幣單位根據小數的位數乘以相應的倍數便可,這樣就能夠避免浮點計算的不精確和decimal精確計算的代價高的問題。編碼
varchar類型用於存儲可變長度的字符串,是最多見的字符串數據類型,它比定長類型更加的節省空間,由於它僅僅使用必要的空間,字符串越短存儲空間越小;varchar須要使用1到2個額外的字節來記錄字符串的長度:若是字符串長度小於255使用1個字節記錄反之使用兩個字節存儲。好比varchar(1000)它須要1002個字節,由於須要兩個字節存儲字符串的長度。spa
在下面的幾種狀況下使用varchar是合適的:字符串列的最大長度比平均長度大不少;列的更新不多;使用了utf-8這樣的複雜的字符集。
char類型是定長的:MySQL老是根據定義的字符集長度分配足夠的空間。char適合存儲很短的字符串,或者全部值都接近同一個長度。例如char很是的適合存儲密碼的MD5值,由於這些值得長度都定長。對於常常變更的值使用char比varchar更好,由於定長的char類型不容易產生碎片。對於很是短的列,char比varchar在存儲空間上也有更好的效率。好比在存儲「是」和「否」使用char(1)只使用一個字節,使用varchar(1)卻須要兩個字節,另外一個來存儲記錄的長度。
它們兩個都被設計來存儲很大的字符串類型的數據,blog使用二進制方式存儲沒有排序規則或字符集,text使用字符串方式存儲有排序規則和字符集。與其餘數據類型不一樣的是:MySQL把bolb和text值當作一個獨立的對象處理。當它們的值太大時,InnoDB會使用專門的「外部」存儲區域進行存儲,這時每一個值在行內須要1--4個字節存儲一個指針,而後在外部存儲真實的值。
對於bolb和text的排序規則也和其餘的數據類型不一樣:bolb和text會對其中前sort_length字符排序,二不是整個字符串排序,還能夠指定前多少個字符進行排序,只須要減小max_sort_length的配置便可。
這個類型能保存最大範圍的值,從1001年到9999年,精度爲秒。它把日期和時間封裝到YYYYMMDDHHMMSS的整數中,使用8個字節的存儲空間。
這個類型能保存最大範圍的值,從1970年1月1日年到2038年,精度爲秒。它只使用4個字節的存儲空間,MySQL提供了from_unixtime()函數把unix時間戳轉化爲日期格式,和unix_timestamp()把日期格式轉化爲時間戳格式。
若是插入的時候timetamp沒有指定具體的時間,MySQL會設置這個列爲當前的時間,更新的時候回指定更新的時間爲當前時間。而datetime則不具備這特性。
除了特殊狀況下選擇datetime(存儲時間範圍很大),其餘狀況下首選timestamp,由於它的空間效率更高。
MySQL只支持最小以秒爲單位的時間類型,若是須要存儲比秒級別更小的時間該任何實現呢?可使用bigint類型存儲微秒級別的時間戳,或者使用double存儲秒以後的小數部分。
MySQL存儲引擎在工做的時候須要在服務器層和存儲引擎之間經過行緩衝格式拷貝數據,而後在服務器層將緩衝內容解碼成各個列。從行緩衝中將編碼過的列傳換成數據結構的操做代價是很是高的(注意:MyISAM的定長行結構實際上與服務器層的行結構匹配,因此不須要轉化)。當一個表列很是多,可是咱們使用到的卻只有幾列時,這時轉化代價就很是的大。
MySQL限制了每一個關聯的操做最多隻能有61個表,可是事實上咱們一般狀況下有可能會超過這個值,並且就算是在61個表之下,解析和優化查詢的代價也是很是大的。一個經驗就是,若是但願執行查詢得快速而且併發性好,單個查詢最好是在12個表之內作關聯。