MySQL里面的utf8与utf8mb4有什么区别呢?
最近发现公司有一部分表使用的是utf8mb4字符集,之前没有用过,看起来好像有点关系,但是又说不清,看了官方文档,翻译总结为本文。
名词解释
BMP字符
Unicode采用基于平面的设计,平面有点像网络协议的分层,每层实现不同的逻辑。而Unicode的每个平面表示的字符是不同的,最基本的就是BMP(Basic Multilingual Plane),中文名称为基本多文种平面。
对应的Unicode标识范围是U+0000 - U+FFFF
,根据下表可以看出对应的二进制最多占用3字节。
补充字符
同理,补充字符就是除了BMP之外的一些字符,可以概括为补充平面。
这些字符可能并不常见,从维基百科的第二辅助平面找到了一个汉字“𦡦”,通过下面的sql可以对比两个字符集,可以发现utf8mb3不支持这个汉字。
select _utf8mb3 '𦡦';
select _utf8mb4 '𦡦';
-- 或者用这种语法
SELECT CAST('𦡦' AS CHAR CHARACTER SET utf8);
SELECT CAST('𦡦' AS CHAR CHARACTER SET utf8mb4);
先说结论
utf8在MySQL内部是utf8mb3,顾名思义最多占用三字节,但是我们印象中的utf8最多是占用四字节的,其实MySQL的utf8是简化版的字符集,而他与四字节的utf8相差的就是上述的补充字符。
我个人理解MySQL这个样的设计是从灵活性和性能方面来考虑的,因为补充字符的应用场景有限,部分场景下使用utf8mb3就能满足使用。 如果都用utf8mb4,虽然相同字符存储空间占用一样,但是utf8mb4的排序规则应该要比utf8mb3更复杂,在处理类似排序、比较等逻辑上可能占用的资源更多。(猜测,未经实验)
如果需要补充字符,使用utf8mb4。
实际情况可根据需求酌情选择。
文档翻译
utf8
utf8又名utf8mb3,隐式对存储的字符做了限制,是3字节UTF-8 unicode编码。
utf8mb3有如下特性:
- 仅支持BMP字符,不支持补充字符
- 每个多字节字符最多占用三个字节
应用如果需要存储补充字符,可使用utf8mb4。
utf8mb3与ucs2提供了完全相同的字符集。
utf8mb3能应用于CHARACTER SET
子句和utf8mb3_collation_substring
校对规则子句,这里的collation_substring
可以是bin, czech_ci, danish_ci, esperanto_ci, estonian_ci
等等,例如:
CREATE TABLE t (s1 CHAR(1) CHARACTER SET utf8mb3;
SELECT * FROM t WHERE s1 COLLATE utf8mb3_general_ci = 'x';
DECLARE x VARCHAR(5) CHARACTER SET utf8mb3 COLLATE utf8mb3_danish_ci;
SELECT CAST('a' AS CHAR CHARACTER SET utf8) COLLATE utf8_czech_ci;
MySQL内部会立刻转换utf8mb3为utf8,所以在下面的语句中看到的都是utf8
或utf8_collation_substring
。
SHOW CREATE TABLE t1;
SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLUMNS;
SELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS;
除了上面的应用,还可以用在其他位置,例如:
mysqld --character-set-server=utf8mb3
SET NAMES 'utf8mb3'; /* 其他有类似效果的SET语句 */
SELECT _utf8mb3 'a';
utf8mb4
utf8mb4,4字节UTF-8 unicode编码。
utf8mb4有一下特性:
- 支持BMP和补充字符
- 每个多字节字符最多占用四个字节
对比utf8mb3字符集:
- 对于BMP字符,utf8mb3和utf8mb4具有相同的存储特征:相同的字面值,相同的编码,相同的大小
- 对于补充字符,utf8mb4需要四字节存储,而utf8mb3不能存储这些字符。当要把utf8mb3的列转换为utf8mb4的时候,不需要担心补充字符的转换,因为根本就不存在(译注:向utf8mb3字符集的列写入补充字符时,sql会提示越界,无法写入)
utf8mb4是utf8mb3的超集(译注:转换操作类似编程语言中的类型转换,小转大),如下拼接的操作,结果是utf8mb4
字符集和utf8mb4_col
列的校对规则:
SELECT CONCAT(utf8mb3_col, utf8mb4_col);
同样的,下面的where子句的比较也是按照utf8mb4_col
列的校对规则进行:
SELECT * FROM utf8mb3_tbl, utf8mb4_tbl
WHERE utf8mb3_tbl.utf8mb3_col = utf8mb4_tbl.utf8mb4_col;
参考链接
- 10.9.2 The utf8mb3 Character Set (3-Byte UTF-8 Unicode Encoding)
- 10.9.1 The utf8mb4 Character Set (4-Byte UTF-8 Unicode Encoding)
- Unicode字符平面映射
- UTF-8
(完)
- 本文作者:吴泽辉
- 本文链接:https://mutex.top/posts/1197e3d5/
- 发表日期:2020年3月16日
- 版权声明:本文章为原创,采用《知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议》进行许可