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/

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