utf8 與 utf8mb4
標准的 UTF-8 字符集編碼是可以用 1~4 個字節去編碼21位字符,是一種變長的編碼格式,這幾乎包含了是世界上所有能看見的語言了。然而在MySQL里實現的utf8最長使用3個字節,節省空間但不能表達全部的UTF-8,只支持到了 Unicode 中的“基本多文種平面”(U+0000至U+FFFF,Basic Multilingual Plane,BMP),包含了控制符、拉丁文,中、日、韓等絕大多數國際字符,但並不是所有,最常見的就算現在手機端常用的表情字符 emoji和一些不常用的漢字,如 “墅” ,這些需要四個字節才能編碼出來。
MySQL在 5.5.3 之后增加了 utf8mb4 字符編碼,mb4即 most bytes 4,使用4個字節來表示完整的UTF-8。簡單說 utf8mb4 是 utf8 的超集並完全兼容utf8,能夠用四個字節存儲更多的字符。
注:QQ里面的內置的表情不算,它是通過特殊映射到的一個gif圖片。一般輸入法自帶的就是。
當你的數據庫里要求能夠存入這些表情或寬字符時,可以把字段定義為 utf8mb4,同時要注意連接字符集也要設置為utf8mb4,否則在 嚴格模式 下會出現 Incorrect string value: /xF0/xA1/x8B/xBE/xE5/xA2… for column 'name'這樣的錯誤,非嚴格模式下此后的數據會被截斷。
utf8mb4_bin、utf8mb4_unicode_ci 與 utf8mb4_general_ci
utf8mb4_bin: 將字符串每個字符用二進制數據編譯存儲,區分大小寫,而且可以存二進制的內容。
utf8mb4_general_ci:ci即case insensitive,不區分大小寫。是一個遺留的 校對規則,不支持擴展,它僅能夠在字符之間進行逐個比較,沒有實現Unicode排序規則,在遇到某些特殊語言或者字符集,排序結果可能不一致。但是,在絕大多數情況下,這些特殊字符的順序並不需要那么精確。
utf8mb4_unicode_ci:是基於標准的Unicode來排序和比較,能夠在各種語言之間精確排序,Unicode排序規則為了能夠處理特殊字符的情況,實現了略微復雜的排序算法。
collate規則:
utf8mb4_bin 大小寫敏感
utf8mb4_general_cs 大小寫敏感
*_bin: 表示的是binary case sensitive collation,也就是說是區分大小寫的
*_cs: case sensitive collation,區分大小寫
*_ci: case insensitive collation,不區分大小寫
Mysql默認的字符檢索策略:utf8_general_ci,表示不區分大小寫;utf8_general_cs表示區分大小寫,utf8_bin表示二進制比較,同樣也區分大小寫 。(注意:在Mysql5.6.10版本中,不支持utf8_genral_cs!)
utf8mb4_general_ci P=p Q=q R=r=Ř=ř S=s=ß=Ś=ś=Ş=ş=Š=š sh ss sz
utf8mb4_unicode_ci P=p Q=q R=r=Ř=ř S=s=Ś=ś=Ş=ş=Š=š sh ss=ß sz
如何選擇
字符除了需要存儲,還需要排序或比較大小,涉及到與編碼字符集對應的 排序字符集(collation)。ut8mb4對應的排序字符集常用的有 utf8mb4_unicode_ci、utf8mb4_general_ci
主要從排序准確性和性能兩方面看:
-
准確性
utf8mb4_unicode_ci: 是基於標准的Unicode來排序和比較,能夠在各種語言之間精確排序。
utf8mb4_general_ci: 沒有實現Unicode排序規則,在遇到某些特殊語言或字符是,排序結果可能不是所期望的。
但是在絕大多數情況下,這種特殊字符的順序一定要那么精確嗎。比如Unicode把ß、Œ當成ss和OE來看;而general會把它們當成s、e,再如ÀÁÅåāă各自都與 A 相等。
-
性能
utf8mb4_general_ci: 在比較和排序的時候更快
utf8mb4_unicode_ci: 在特殊情況下,Unicode排序規則為了能夠處理特殊字符的情況,實現了略微復雜的排序算法。
但是在絕大多數情況下,不會發生此類復雜比較。general理論上比Unicode可能快些,但相比現在的CPU來說,它遠遠不足以成為考慮性能的因素,索引涉及、SQL設計才是。
這也從另一個角度告訴我們,不要可能產生亂碼的字段作為主鍵或唯一索引。例如:以url來作為唯一索引,但是它記錄的有可能是亂碼。
總結:utf8mb4_general_ci 更快,utf8mb4_unicode_ci 更准確。推薦是 utf8mb4_unicode_ci,將來 8.0 里也極有可能使用變為默認的規則。相比選擇哪一種collation,使用者更應該關心字符集與排序規則在db里需要統一。
參考:
http://seanlook.com/2016/10/23/mysql-utf8mb4/
https://my.oschina.net/xsh1208/blog/1052781