MySQL中的字符集和比較規則

如果你還因爲MySQL亂碼摸不着頭腦,如果你只知道存儲emoji表情時,需要使用utf8mb4,但卻不知道爲什麼,那麼本篇文章或許能解開你的一些疑惑。

字符集和排序規則

什麼是字符集:

字符集指的是某個字符範圍的編碼規則,一個字符映射成一個二進制數據的過程也叫做編碼,將一個二進制數據映射到一個字符的過程叫做解碼

什麼是比較規則:

比較規則是針對某個字符集中的字符比較大小的一種規則。在我們確定了字符集表示字符的範圍以及編碼規則後,怎麼比較兩個字符的大小呢?最容易想到的就是直接比較這兩個字符對應的二進制編碼的大小,比方說字符'a'的編碼爲0x01,字符'b'的編碼爲0x02,所以'a'小於'b',這種簡單的比較規則也可以被稱爲二進制比較規則。當然比較規則有很多種,這裏我們只要理解什麼是比較規則就行了。

一些重要的字符集:

字符集有很多種,來看一下有哪些常見的:

  • ASCII字符集

    共收錄128個字符,包括空格、標點符號、數字、大小寫字母和一些不可見字符。由於總共才128個字符,所以可以使用1個字節來進行編碼,我們看一些字符的編碼方式:

    'L' ->  01001100(十六進制:0x4C,十進制:76)
    'M' ->  01001101(十六進制:0x4D,十進制:77)
    
  • ISO 8859-1字符集

    共收錄256個字符,是在ASCII字符集的基礎上又擴充了128個西歐常用字符(包括德法兩國的字母),也可以使用1個字節來進行編碼。這個字符集也有一個別名latin1

  • GB2312字符集

    收錄了漢字以及拉丁字母、希臘字母、日文平假名及片假名字母、俄語西裏爾字母。其中收錄漢字6763個,其他文字符號682個。同時這種字符集又兼容ASCII字符集。

  • GBK字符集

    GBK字符集只是在收錄字符範圍上對GB2312字符集作了擴充,編碼方式上兼容GB2312

  • utf8字符集

    收錄地球上能想到的所有字符,而且還在不斷擴充。這種字符集兼容ASCII字符集,採用變長編碼方式,編碼一個字符需要使用1~4個字節,比方說這樣:

    'L' -> 01001100(十六進制:0x4C)
    '啊' ->  111001011001010110001010(十六進制:0xE5958A)
    

對於同一個字符,不同字符集也可能有不同的編碼方式。比如對於漢字'我'來說,ASCII字符集中根本沒有收錄這個字符,utf8gb2312字符集對漢字的編碼方式如下:

utf8編碼:111001101000100010010001 (3個字節,十六進制表示是:0xE68891)
gb2312編碼:1011000010101110 (2個字節,十六進制表示是:0xB0AE)

MySQL中支持的字符集和排序規則

MySQL中的utf8和utf8mb4

我們上邊說utf8字符集表示一個字符需要使用1~4個字節,但是我們常用的一些字符使用1~3個字節就可以表示了。而在MySQL中字符集表示一個字符所用最大字節長度在某些方面會影響系統的存儲和性能,所以MySQL中定義了:

  • utf8mb3:閹割過的utf8字符集,只使用1~3個字節表示字符。
  • utf8mb4:正宗的utf8字符集,使用1~4個字節表示字符。

有一點需要大家十分的注意,在MySQLutf8utf8mb3的別名,所以之後在MySQL中提到utf8就意味着使用1~3個字節來表示一個字符,如果大家有使用4字節編碼一個字符的情況,比如存儲一些emoji表情啥的,那請使用utf8mb4

MySQL中支持幾十種字符集,這裏列出來幾個,Maxlen代表該種字符集表示一個字符最多需要幾個字節

字符集名稱 Maxlen
ascii 1
latin1 1
gb2312 2
gbk 2
utf8 3
utf8mb4 4
比較規則

一種字符集往往對應着若干種比較規則,MySQL支持的字符集就已經非常多了,所以支持的比較規則更多,我們先只查看一下utf8字符集下的比較規則:

mysql> SHOW COLLATION LIKE 'utf8\_%';
+--------------------------+---------+-----+---------+----------+---------+
| Collation                | Charset | Id  | Default | Compiled | Sortlen |
+--------------------------+---------+-----+---------+----------+---------+
| utf8_general_ci          | utf8    |  33 | Yes     | Yes      |       1 |
| utf8_bin                 | utf8    |  83 |         | Yes      |       1 |
| utf8_unicode_ci          | utf8    | 192 |         | Yes      |       8 |
| utf8_icelandic_ci        | utf8    | 193 |         | Yes      |       8 |
| utf8_latvian_ci          | utf8    | 194 |         | Yes      |       8 |
......
| utf8_german2_ci          | utf8    | 212 |         | Yes      |       8 |
| utf8_croatian_ci         | utf8    | 213 |         | Yes      |       8 |
| utf8_unicode_520_ci      | utf8    | 214 |         | Yes      |       8 |
| utf8_vietnamese_ci       | utf8    | 215 |         | Yes      |       8 |
| utf8_general_mysql500_ci | utf8    | 223 |         | Yes      |       1 |
+--------------------------+---------+-----+---------+----------+---------+
27 rows in set (0.00 sec)

這些比較規則的命名還挺有規律的,具體規律如下:

  • 比較規則名稱以與其關聯的字符集的名稱開頭。如上圖的查詢結果的比較規則名稱都是以utf8開頭的。

  • 後邊緊跟着該比較規則主要作用於哪種語言,比如utf8_polish_ci表示以波蘭語的規則比較,utf8_spanish_ci是以西班牙語的規則比較,utf8_general_ci是一種通用的比較規則。

  • 名稱後綴意味着該比較規則是否區分語言中的重音、大小寫啥的,具體可以用的值如下:

    後綴 英文釋義 描述
    _ai accent insensitive 不區分重音
    _as accent sensitive 區分重音
    _ci case insensitive 不區分大小寫
    _cs case sensitive 區分大小寫
    _bin binary 以二進制方式比較

    比如utf8_general_ci這個比較規則是以ci結尾的,說明不區分大小寫。

每種字符集對應若干種比較規則,每種字符集都有一種默認的比較規則,SHOW COLLATION的返回結果中的Default列的值爲YES的就是該字符集的默認比較規則,比方說utf8字符集默認的比較規則就是utf8_general_ci

感謝: MySQL 是怎樣運行的:從根兒上理解 MySQL

參考: https://dev.mysql.com/doc/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章