MySQL中 utf8 和 utf8mb4 的区别,以及 general_ci 、unicode_ci和unicode_520_ci的区别

本文深入解析Unicode编码原理,探讨UTF-8及其在MySQL中的应用,包括utf8与utf8mb4的区别,以及不同排序算法如general_ci、unicode_ci和unicode_520_ci在MySQL中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 首先了解什么是Unicode:

Unicode是一种信息技术(IT)标准,用于对世界上大多数书写系统中表示的文本进行一致的编码,表示和处理。

大致意思就是Unicode对英文字符、符号、汉字、表情符号制定的统一数字码表,例如:

大写字母 M :二进制是 1001101,十进制是 77,十六进制是 4d
汉字 :二进制是101001001001101,十进制是21069,十六进制是524d

但是计算机不能直接拿这个数字码表来进行字符存储,因为里面没有表示截断的部分,计算机不知道该什么时候一个字符表示完了。

计算机是字节存储(就是八位二进制)

M 如果直接存储就是:                  01001101
前 如果直接存储就是:01010010 01001101

可以看到 M 最后的码表是一样的,计算机无法判断:是 M 或者是 的后半段。

  1. UTF-8 就是对 Unicode 中的所有字符进行编码的一种格式。它的编码规范是:

一、对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
二、对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的有效 Unicode 码。

对应出来的规范表格(x是Unicode有效码):

字节数第一个码点(十六进制)最后的码点(十六进制)字节一字节二字节三字节四
1U+0000U+007F0xxxxxxx
2U+0080U+07FF110xxxxx10xxxxxx
3U+0800U+FFFF1110xxxx10xxxxxx 10xxxxxx
4U+10000U+10FFFF11110xxx10xxxxxx 10xxxxxx10xxxxxx

那么按照上面的表格, 十六进制:524d,属于0800-FFFF,表示为3个字节。UTF-8应该是(从后往前转换、高位不足补零):

11100101 10001001 10001101

  1. 基础知识有了,那么MySQL中的 utf8 和 utf8mb4 有什么区别

其实 MySQL中的utf8utf8mb3,只能表示1-3个字节,因为当时的字符还没有这么多,MySQL的开发者认为3个字节足够表示所有Unicode字符做的反向优化

如今emoji表情和其他字符的加入,使得 utf8mb3 不够表示,所有添加了utf8mb4,遵守 UTF-8 编码格式,可以表示4个字节的字符。

由于 MySQL中的 utf8 名称已经被 utf8mb3 占用,所以只能将真正的遵守UTF-8编码格式字符集起名为 utf8mb4。

现在MySQL8.0已经默认使用utf8mb4,官网也声明:

utf8mb3 已经弃用,会在将来的版本进行删除。现如今的 utf8 含义混淆,请显式指定为 utf8mb4

  1. general_ci 、 unicode_ci 和 unicode_520_ci 的区别:

这几种都是MySQL中 字符集编码的排序算法

unicode_ci是遵守的Unicode组织的4.0.0归类算法排序(有一部分没有实现:一些越南语等小语种排序) Unicode UCA 权重排名4.0.0版本
unicode_520_ci 则是基于 5.2.0 新版本实现。还有 utf8mb4_0900_ai_ci 是基于更高的 9.0.0版本实现。

general_ci 则是在 unicode_ci 排序上做了一定优化,排序效率提高了一点(?十分之一左右)。只支持单字符对比排序。

例如:

在德语中 ß 书写为 ss
unicode_ci 只有 ß = ss,单个 s 和 ß 是不同的。
general_ci 做了优化,只支持单字符比较,但是又需要 对 ß 进行排序,所以结果是:ß = s

在StackOverflow中推荐是使用 unicode_ci,因为general_ci的效率提升有限。
而且推荐使用最新的 utf8mb4_0900_ai_ci ,因为Unicode组织也不是吃白饭的。

我认为的话,在国内环境下还是使用 general_ci,对于项目经理来说,他一定会放大 unicode_ci 10%性能的严重性,而且字符排序的准确度也没有那么重要。

参考资料:
1.MySQL官网:MySQL 8.0参考手册:Unicode字符集
2.Wiki:德语中的ß
3.StackOverflow:general_ci 和 unicode_ci
4.Wiki:Unicode
5.Wiki:UTF-8

### UTF8MB4_UNICODE_CI UTF8MB4_GENERAL_CI 的差异 在 MySQL 中,`utf8mb4_unicode_ci` `utf8mb4_general_ci` 是两种不同的排序规则(collation),用于处理字符集 `utf8mb4` 下字符串的比较排序。 #### 字符串比较准确性 `utf8mb4_unicode_ci` 排序规则基于 Unicode 标准实现更严格的语言敏感性。这种排序方式考虑到了更多复杂的语言特性,如重音符号、变音符号其他特殊字符的区别[^1]。因此,在多语言环境中特别是对于欧洲语言的支持更为精准。 相比之下,`utf8mb4_general_ci` 则采用了较为宽松的方式来进行字符匹配与排序操作。它忽略了某些细节上的差别,比如不同形式的字母可能被视为相同对待;这使得其性能通常优于前者但在特定情况下可能会丢失一些细微的语言特征[^2]。 #### 性能表现 由于 `utf8mb4_unicode_ci` 需要执行更加细致入微的文字分析工作来确保正确无误地识别各种文字形态及其含义关联,所以在实际应用过程中往往伴随着更高的计算成本以及相对较慢的速度体验。而另一方面,`utf8mb4_general_ci` 因为其简化了部分逻辑判断流程从而获得了更好的效率优势[^3]。 ```sql SELECT 'é' = 'e' COLLATE utf8mb4_unicode_ci AS unicode_result, 'é' = 'e' COLLATE utf8mb4_general_ci AS general_result; ``` 上述 SQL 查询展示了两个排序规则下对带重音符号的小写字母 "é" 与普通小写英文字母 "e" 进行相等性测试的结果对比情况: - 使用 `utf8mb4_unicode_ci` 返回 false 表明两者并不认为是相同的; - 而采用 `utf8mb4_general_ci` 则会返回 true 认定它们可以互换使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值