0%

MySQL字符集与排序规则

结论

建议字符集使用utf8mb4,排序规则使用utf8mb4_bin

字符集(utf-8与utf8mb4)

mysql 的 UTF-8

  • utf8mb3 :阉割过的 utf8 字符集,只使用1~3个字节表示字符。

  • utf8mb4 :正宗的 utf8 字符集,使用1~4个字节表示字符。

有一点需要大家十分的注意,在 MySQL 中 utf8 是 utf8mb3 的别名,所以之后在 MySQL 中提到 utf8 就意味着使用1~3个字节来表示一个字符,如果大家有使用4字节编码一个字符的情况,比如存储一些emoji表情啥的,那请

使用 utf8mb4 。

utf8mb4的含义

mb4:即 most bytes 4,使用4个字节来表示完整的UTF-8。

utf8mb4 是utf8的超集并完全兼容utf8,能够用四个字节存储更多的字符。

查看当前 MySQL 中支持的字符集

1
SHOW (CHARACTER SET|CHARSET) [LIKE 匹配的模式];

排序规则

_bin: binary case sensitive collation,也就是说是区分大小写的
_cs: case sensitive collation,区分大小写
_ci: case insensitive collation,不区分大小写

utf8mb4_bin

将字符串每个字符用二进制数据编译存储,区分大小写,而且可以存二进制的内容。

utf8mb4_general_ci

ci即case insensitive,不区分大小写。没有实现Unicode排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。但是,在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。

是一个遗留的 校对规则,不支持扩展,它仅能够在字符之间进行逐个比较。utf8_general_ci校对规则进行的比较速度很快,但是与使用 utf8mb4_unicode_ci的校对规则相比,比较正确性较差。

utf8mb4_unicode_ci

是基于 标准Unicode 来排序和比较,能够在各种语言之间精确排序,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。

utf8mb4_general_ci VS utf8mb4_unicode_ci

准确性:

  • utf8mb4_unicode_ci是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序
  • utf8mb4_general_ci没有实现Unicode排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。

但是,在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。

性能

  • utf8mb4_general_ci在比较和排序的时候更快
  • utf8mb4_unicode_ci在特殊情况下,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。

但是在绝大多数情况下发,不会发生此类复杂比较。相比选择哪一种collation,使用者更应该关心字符集与排序规则在db里需要统一。

查看 MySQL 中支持的比较规则的命令

1
SHOW COLLATION [LIKE 匹配的模式];

字符集和比较规则的应用

MySQL 有4个级别的字符集和比较规则,分别是:

  • 服务器级别

  • 数据库级别

  • 表级别

  • 列级别

服务器级别

1
2
3
4
# 查字符集
SHOW VARIABLES LIKE 'character_set_server';
# 查比较规则
SHOW VARIABLES LIKE 'collation_server';

配置文件

1
2
3
[server]
character_set_server=gbk
collation_server=gbk_chinese_ci

数据库级别

如果想查看当前数据库使用的字符集和比较规则,可以查看下面两个系统变量的值(前提是使用 USE 语句选择当

前默认数据库,如果没有默认数据库,则变量与相应的服务器级系统变量具有相同的值):

1
2
3
4
5
6
# 选择数据库
USE charset_demo_db;
# 查字符集
SHOW VARIABLES LIKE 'character_set_server';
# 查比较规则
SHOW VARIABLES LIKE 'collation_server';

character_set_database 和 collation_database 这两个系统变量是只读的,我们不能通过修改这两个变量的值而改变当前数据库的字符集和比较规则。

表级别

我们也可以在创建和修改表的时候指定表的字符集和比较规则。

1
2
3
4
5
6
CREATE TABLE 表名 (列的信息)
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称]]
ALTER TABLE 表名
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称]

列级别

需要注意的是,对于存储字符串的列,同一个表中的不同的列也可以有不同的字符集和比较规则。我们在创建和修改列定义的时候可以指定该列的字符集和比较规则。

1
2
3
4
CREATE TABLE 表名(
列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],
其他列...
);

仅修改字符集或仅修改比较规则

由于字符集和比较规则是互相有联系的,如果我们只修改了字符集,比较规则也会跟着变化,如果只修改了比较

规则,字符集也会跟着变化,具体规则如下:

  • 只修改字符集,则比较规则将变为修改后的字符集默认的比较规则。

  • 只修改比较规则,则字符集将变为修改后的比较规则对应的字符集。

各级别字符集和比较规则小结

  • 如果创建或修改列时没有显式的指定字符集和比较规则,则该列默认用表的字符集和比较规则

  • 如果创建或修改表时没有显式的指定字符集和比较规则,则该表默认用数据库的字符集和比较规则

  • 如果创建或修改数据库时没有显式的指定字符集和比较规则,则该数据库默认用服务器的字符集和比较规则