一、資料型別的選擇
MySQL的資料型別有很多種,選擇正確的資料型別對于獲得高性能特別地重要,如何選擇合適的資料型別呢?主要遵從以下三個原則:
1.更小的通常情況下性能更好
一般情況下,應該盡量使用可以正確存盤資料的最小資料型別,比如只需存盤0--200的整數,則使用 tinyint unsigned 會比 int 好,更小的資料型別通常更快,因為它們占用更小的磁盤、記憶體和CPU快取,并且處理時需要的CPU周期也更少,因此在選擇的時候應該選擇你認為不會超出范圍的最小資料型別,
2.簡單即為最好
簡單資料型別的操作通常情況下需要的CPU周期更小,比如,整型比字串操作代價更低,因為字符集和校對規則使得字符的比較比整型比較更加的復雜(如:存盤時間通常使用date、time、datetime 比 使用字串存盤性能更好),
3.盡量避免NULL
在設計表結構時,最好指定列為NOT NUll,除非真正的需要存盤NULL值,
解釋:如果在查詢的時候包含有NULL的列,對于MYSQL來說更加的難以優化,因為可以為NULL的列使得索引、索引統計和值比較都非常的復雜,可為NULL的列會使用更多的存盤空間,在MYSQL里面也需要特殊的處理,當可以為NULL的列被索引時,每個索引記錄需要一個額外的位元組,在MyISAM里甚至還可能導致固定大小的索引變為可更改大小的索引(意味著性能受到影響)
二、常見的幾種資料型別
1.整數型別
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)沒有任何的區別,
2.實數型別
可以使用decimal存盤比bigint還大的整數,decimal用來存盤精確的小數,在MySQL5.0以上的版本中decimal還支持高精度的計算,decimal可以指定小數點前后所允許的最大位數,MySQL會將數字打包存盤在一個二進制的字串中,浮點型別在存盤同樣范圍的值時,通常比decimal使用更少的空間,
選擇:因為需要額外的空間計算和開銷,所以應該盡量只在對小數進行計算的時候才使用decimal----涉及到財務計算類的業務,但是在資料量比較大的時候可以考慮使用bigint代替decimal,將需要存盤的貨幣單位根據小數的位數乘以相應的倍數即可,這樣就可以避免浮點計算的不精確和decimal精確計算的代價高的問題,
3.字串型別
varchar型別:
varchar型別用于存盤可變長度的字串,是最常見的字串資料型別,它比定長型別更加的節省空間,因為它僅僅使用必要的空間,字串越短存盤空間越小;varchar需要使用1到2個額外的位元組來記錄字串的長度:如果字串長度小于255使用1個位元組記錄反之使用兩個位元組存盤,比如varchar(1000)它需要1002個位元組,因為需要兩個位元組存盤字串的長度,
在下面的幾種情況下使用varchar是合適的:字串列的最大長度比平均長度大很多;列的更新很少;使用了utf-8這樣的復雜的字符集,
char型別:
char型別是定長的:MySQL總是根據定義的字符集長度分配足夠的空間,char適合存盤很短的字串,或者所有值都接近同一個長度,例如char非常的適合存盤密碼的MD5值,因為這些值得長度都定長,對于經常變動的值使用char比varchar更好,因為定長的char型別不容易產生碎片,對于非常短的列,char比varchar在存盤空間上也有更好的效率,比如在存盤“是”和“否”使用char(1)只使用一個位元組,使用varchar(1)卻需要兩個位元組,另一個來存盤記錄的長度,
4.blob和text型別
它們兩個都被設計來存盤很大的字串型別的資料,blog使用二進制方式存盤沒有排序規則或字符集,text使用字串方式存盤有排序規則和字符集,與其他資料型別不同的是:MySQL把bolb和text值當做一個獨立的物件處理,當它們的值太大時,InnoDB會使用專門的“外部”存盤區域進行存盤,這時每個值在行內需要1--4個位元組存盤一個指標,然后在外部存盤真實的值,
對于bolb和text的排序規則也和其他的資料型別不同:bolb和text會對其中前sort_length字符排序,二不是整個字串排序,還可以指定前多少個字符進行排序,只需要減少max_sort_length的配置即可,
5.日期和時間型別
datetime型別:
這個型別能保存最大范圍的值,從1001年到9999年,精度為秒,它把日期和時間封裝到YYYYMMDDHHMMSS的整數中,使用8個位元組的存盤空間,
timestamp型別:
這個型別能保存最大范圍的值,從1970年1月1日年到2038年,精度為秒,它只使用4個位元組的存盤空間,MySQL提供了from_unixtime()函式把unix時間戳轉化為日期格式,和unix_timestamp()把日期格式轉化為時間戳格式,
區別:
如果插入的時候timetamp沒有指定具體的時間,MySQL會設定這個列為當前的時間,更新的時候回指定更新的時間為當前時間,而datetime則不具有這特性,
選擇:
除了特殊情況下選擇datetime(存盤時間范圍很大),其他情況下首選timestamp,因為它的空間效率更高,
MySQL只支持最小以秒為單位的時間型別,如果需要存盤比秒級別更小的時間該任何實作呢?可以使用bigint型別存盤微秒級別的時間戳,或者使用double存盤秒之后的小數部分,
三、MySQL設計中的一些陷阱
1.太多的列
MySQL存盤引擎在作業的時候需要在服務器層和存盤引擎之間通過行緩沖格式拷貝資料,然后在服務器層將緩沖內容解碼成各個列,從行緩沖中將編碼過的列傳換成資料結構的操作代價是非常高的(注意:MyISAM的定長行結構實際上與服務器層的行結構匹配,所以不需要轉化),當一個表列非常多,但是我們使用到的卻只有幾列時,這時轉化代價就非常的大,
2.太對關聯的表
MySQL限制了每個關聯的操作最多只能有61個表,但是事實上我們通常情況下有可能會超過這個值,而且就算是在61個表之下,決議和優化查詢的代價也是非常大的,一個經驗就是,如果希望執行查詢得快速并且并發性好,單個查詢最好是在12個表以內做關聯,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/243522.html
標籤:其他
上一篇:ashtop學習分享
下一篇:Mysql基礎知識
