【MySQL系列】深入理解MySQL中的存储、排序字符集

前言
在创建数据库时,我们经常会需要填写数据库的所用字符集、排序规则,字符集和排序规则是两个非常重要的概念,它们决定了数据库如何存储和比较字符串数据。在 MySQL 中,常用的存储字符集有 utf8、utf8mb4,而排序字符集有 utf8mb4_unicode_ci、utf8mb4_general_ci、utf8mb4_bin、utf8mb4_0900_ai_ci,如下图所示。今天我们来探讨一下MySQL中几种常用的字符集和排序规则之间的区别和适用场景。

一、存储字符集
utf8mb4 和 utf8 是 MySQL 中两种常用的字符集,它们都可以用来存储 Unicode 字符,但是有一些区别和联系。接下来,我们将从以下几个方面对比 utf8mb4 和 utf8。
1.1 字符集简介
utf8 是 Mysql 中最早支持的 Unicode 字符集,是一种可变长度的字符编码方式,可以表示世界上几乎所有的字符。它使用 1 到 3 个字节的 UTF-8 字符,具体取决于字符的编码范围。
要在 Mysql 中保存 4 字节长度的 UTF-8 字符,需要使用 utf8mb4 字符集,但只有 5.5.3 版本以后的才支持。个人觉得,为了获取更好的兼容性,应该总是使用 utf8mb4 而非 utf8。
1.2 区别详解
- 编码范围
- UTF-8 可以表示大多数常见的字符,但对于一些罕见的字符和 emoji 表情等,可能无法正确表示。这些字符需要 4 个字节来编码,所以 utf8 会在遇到这些字符时报错或者出现乱码。
- utf8mb4 则可以表示几乎所有的 Unicode 字符,能够存储 Emoji 表情、部分罕用汉字、新增的 Unicode 字符等。
- 存储需求
- 由于 utf8mb4 可以表示更多的字符,所以它通常需要比 UTF-8 更多的存储空间。具体来说,UTF8MB4 可能需要使用 1 到 4 个字节来表示一个字符,而 UTF-8 通常只需要使用 1 到 3 个字节。
- 对于 CHAR 类型数据,utf8mb4 会多消耗一些空间,根据 Mysql 官方建议,使用 VARCHAR 替代 CHAR。例如,一个 CHAR(10) 类型的字段,如果使用 utf8 字符集,那么它需要保留 10 * 3 = 30 个字节的空间。如果使用 utf8mb4 字符集,那么它需要保留 10 * 4 = 40 个字节的空间。
- 对于 VARCHAR 类型的字段,如果使用 utf8 字符集,那么它需要额外使用一个字节来记录字符串的长度。如果使用 utf8mb4 字符集,那么它需要额外使用两个字节来记录字符串的长度。
- 兼容性
- UTF-8 是一种广泛使用的字符集,几乎所有的操作系统和编程语言都支持它。因此,如果需要与其他系统进行数据交换,UTF-8 可能是一个更好的选择。
- 如果需要支持更广泛的字符范围,或者需要更高的安全性和兼容性,那么应该使用 utf8mb4 字符集。utf8mb4 虽然可以表示更多的字符,但并不是所有的系统都支持它。在使用 utf8mb4 时,需要确保应用程序和数据库服务器都支持这个字符集。
1.3 选择建议
- 如果应用程序只需要处理常见的字符,那么 UTF-8 可能是一个不错的选择,它具有广泛的兼容性和较低的存储需求。
- 如果应用程序需要处理一些罕见的字符或 emoji 表情等,那么 utf8mb4 可能是更好的选择,它可以确保数据能够正确地存储和显示所有的字符。
- 在选择字符集时,还需要考虑数据库的性能和存储需求。如果数据库中存储了大量的文本数据,那么选择一个合适的字符集可以提高数据库的性能和存储效率
总之,UTF-8 和 utf8mb4 都是 MySQL 中常用的字符集选项,都可以用来存储 Unicode 字符,它们之间的区别主要在于编码范围、存储需求和兼容性。在选择字符集时,需要根据应用程序的具体业务需求和实际情况来进行选择,以确保数据能够正确地存储和显示。虽然,utf8mb4 比 utf8 需要更多的存储空间,并且在某些情况下可能会导致性能略有下降。不过在现代硬件和应用场景下,utf8mb4 的性能影响通常可以忽略不计。
二、排序规则
2.1 排序规则概述
排序规则是指在比较和排序字符串时所遵循的规则,用于定义字符的排序和比较方式,而排序规则会影响字符串的比较、排序等操作。不同的字符集可以有不同的排序规则,甚至同一个字符集也可以有多种排序规则。在 MySQL中,比较常用的字符集是utf8和utf8mb4,这两个字符集是类似的,查看下 utf8mb4 字符集下支持的所有比较规则:
SHOW COLLATION LIKE 'utf8\_%';
SHOW COLLATION LIKE 'utf8mb4\_%';
| Collation(排序方式) | Charset(字符集) | Id | Default(默认值) | Compiled | Sortlen(排序) |
|---|---|---|---|---|---|
| utf8mb4_general_ci | utf8mb4 | 45 | Yes | Yes | 1 |
| utf8mb4_bin | utf8mb4 | 46 | Yes | 1 | |
| utf8mb4_unicode_ci | utf8mb4 | 224 | Yes | 8 | |
| utf8mb4_icelandic_ci | utf8mb4 | 225 | Yes | 8 | |
| utf8mb4_latvian_ci | utf8mb4 | 226 | Yes | 8 | |
| utf8mb4_romanian_ci | utf8mb4 | 227 | Yes | 8 | |
| utf8mb4_slovenian_ci | utf8mb4 | 228 | Yes | 8 | |
| utf8mb4_polish_ci | utf8mb4 | 229 | Yes | 8 | |
| utf8mb4_estonian_ci | utf8mb4 | 230 | Yes | 8 | |
| utf8mb4_spanish_ci | utf8mb4 | 231 | Yes | 8 | |
| utf8mb4_swedish_ci | utf8mb4 | 232 | Yes | 8 | |
| utf8mb4_turkish_ci | utf8mb4 | 233 | Yes | 8 | |
| utf8mb4_czech_ci | utf8mb4 | 234 | Yes | 8 | |
| utf8mb4_danish_ci | utf8mb4 | 235 | Yes | 8 | |
| utf8mb4_lithuanian_ci | utf8mb4 | 236 | Yes | 8 | |
| utf8mb4_slovak_ci | utf8mb4 | 237 | Yes | 8 | |
| utf8mb4_spanish2_ci | utf8mb4 | 238 | Yes | 8 | |
| utf8mb4_roman_ci | utf8mb4 | 239 | Yes | 8 | |
| utf8mb4_persian_ci | utf8mb4 | 240 | Yes | 8 | |
| utf8mb4_esperanto_ci | utf8mb4 | 241 | Yes | 8 | |
| utf8mb4_hungarian_ci | utf8mb4 | 242 | Yes | 8 | |
| utf8mb4_sinhala_ci | utf8mb4 | 243 | Yes | 8 | |
| utf8mb4_german2_ci | utf8mb4 | 244 | Yes | 8 | |
| utf8mb4_croatian_ci | utf8mb4 | 245 | Yes | 8 | |
| utf8mb4_unicode_520_ci | utf8mb4 | 246 | Yes | 8 | |
| utf8mb4_vietnamese_ci | utf8mb4 | 247 | Yes | 8 |
这些比较规则的命名还挺有规律的,具体规律如下:
-
比较规则名称以与其关联的字符集的名称开头,如上述查询结果的比较规则名称都是以utf8mb4开头的。
-
后边紧跟着该比较规则主要作用于哪种语言,比如 utf8_polish_ci 表示以波兰语的规则比较,utf8_spanish_ci 是以西班牙语的规则比较,utf8_general_ci 是一种通用的比较规则。
-
名称后缀意味着该比较规则是否区分语言中的重音、大小写啥的,具体可以用的值如下:
后缀 英文释义 描述 _ai accent insensitive 不区分重音。也就是说,排序时 e、è、é、ê 和 ë 之间没有区别。 _as accent sensitive 区分重音。 _ci case insensitive 不区分大小写,即 “大小写不敏感”。 _cs case sensitive 区分大小写,即大小写敏感。 _bin binary 以二进制方式比较,区分大小写和重音符号。
比如 utf8mb4_general_ci 这个比较规则是以 ci 结尾的,说明不区分大小写。每种字符集都有一种默认的比较规则,SHOW COLLATION 返回结果中的Default 列的值为 YES 的就是该字符集的默认比较规则,比如 utf8mb4 字符集默认规则就是utf8mb4_general_ci,又比如utf8字符集默认规则就是 utf8_general_ci。排序规则的不同会影响字符串的比较和排序的结果,进而影响索引的效率和查询的性能。一般来说,_bin 排序规则的性能最高,因为它只需要按照二进制方式比较字符串,不需要考虑字符的大小写和重音符号等因素。_general_ci 排序规则的性能次之,因为它只需要按照一般方式比较字符串,不需要考虑字符的语言或地区等因素。_unicode_ci 和 _ci 排序规则的性能最低,因为它们需要按照 Unicode 标准或特定语言或地区的方式比较字符串,需要考虑字符的大小写和重音符号等因素。
2.2 比较规则
比较规则可以作用于四个级别,分别是服务器级别、数据库级别、表级别、列级别。服务器级别的比较规则由collation_server参数控制,如果创建数据库、表、列时没有显式的指定比较规则,则会继承上一级的比较规则。下面给出创建及修改库、表、列的比较规则的示例语句:
-- 创建数据库指定比较规则
CREATE DATABASE 数据库名[[DEFAULT] CHARACTER SET 字符集名称][[DEFAULT] COLLATE 比较规则名称];-- 修改数据库的比较规则
ALTER DATABASE 数据库名[[DEFAULT] CHARACTER SET 字符集名称][[DEFAULT] COLLATE 比较规则名称];-- 创建表时指定比较规则
CREATE TABLE 表名 (列的信息)[[DEFAULT] CHARACTER SET 字符集名称][COLLATE 比较规则名称]]-- 修改表的比较规则
ALTER TABLE 表名[[DEFAULT] CHARACTER SET 字符集名称][COLLATE 比较规则名称]# 创建时指定列的比较规则
CREATE TABLE 表名(列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],其他列...
);-- 修改列的比较规则
ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];
2.3 排序字符集
utf8 字符集默认规则是 utf8_general_ci,常用到的有utf8_general_ci、utf8_unicode_ci、utf8_bin等。而 utf8mb4 字符集默认规则是utf8mb4_general_ci,常用到的有utf8mb4_general_ci、utf8mb4_unicode_ci、utf8mb4_bin等,其他比较规则基本很少会用,下面简单了解下这几种规则的异同。
utf8_bin、utf8mb4_bin
将字符串每个字符用二进制数据编译存储,区分大小写,也区分重音符号。_bin 的比较方法其实就是直接将所有字符看作二进制串,然后从最高位往最低位比对,所以很显然它是区分大小写的。
utf8_general_ci、utf8mb4_general_ci
utf8_general_ci 是 utf8 字符集的一种排序规则,不区分大小写,也不区分重音符号。utf8mb4_general_ci 是utf8字符集的一种排序规则,不支持扩展,它仅能够在字符之间进行逐个比较,不区分大小写,但会区分重音符号。utf8_general_ci 校对规则进行的比较速度很快,但是与使用 utf8mb4_unicode_ci 的校对规则相比,比较正确性较差。
注意:utf8mb4_general_ci 与 utf8_general_ci 基本兼容,只是前者支持更多字符。
utf8_unicode_ci、utf8mb4_unicode_ci
是基于标准的Unicode来排序和比较,能够在各种语言之间精确排序,Unicode排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。
utf8mb4_0900_ai_ci
MySQL 8.0 默认的是 utf8mb4_0900_ai_ci,属于 utf8mb4_unicode_ci 中的一种。
以前,utf8mb4_general_ci 是默认排序规则。由于 utf8mb4_0900_ai_ci 排序规则现在是默认排序规则,因此默认情况下新表格可以存储基本多语言平面之外的字符。现在可以默认存储表情符号。如果需要重音灵敏度和区分大小写,则可以使用 utf8mb4_0900_as_cs 代替。
三、附录
3.1 utf8mb4_unicode_ci 和 utf8mb4_general_ci 的区别
-
准确性
排序字符集 说明 utf8mb4_unicode_ci 是基于标准的 Unicode 来排序和比较,能够在各种语言之间精确排序。 utf8mb4_general_ci 没有实现 Unicode 排序规则,在遇到某些特殊语言或者字符集,排序结果可能不一致。 注意:在绝大多数情况下,这些特殊字符的顺序并不需要那么精确。
-
性能
排序字符集 说明 utf8mb4_general_ci 在比较和排序的时候更快。 utf8mb4_unicode_ci 在特殊情况下,Unicode 排序规则为了能够处理特殊字符的情况,实现了略微复杂的排序算法。 注意:在绝大多数情况下,不会发生此类复杂比较。
3.2 实践建议
在开发时,个人建议:
- 尽可能使用 utf8mb4 字符集,以确保能够支持完整的 Unicode 字符集。
- 根据具体需求选择合适的排序规则,大多数情况下可以使用 utf8mb4_general_ci。
- 在创建表和列时就指定字符集和排序规则,避免以后出现编码问题。
- 如果需要存储大小写或重音符号敏感的数据,使用 utf8mb4_bin 排序规则。
- 对于加密数据或需要按二进制方式比较的场景,也应该使用 utf8mb4_bin。
四、总结
虽然推荐用 utf8mb4_unicode_ci,但是用 utf8mb4_general_ci 也没啥问题。因为 utf8mb4_unicode_ci 比较准确,utf8mb4_general_ci 速度比较快。通常情况下,新建数据库和创建 varchar 字符集类型字段时,一般选用 utf8mb4_general_ci 就可以。
通过正确设置和使用字符集及排序规则,我们可以有效地在 MySQL 中存储和处理 Unicode 字符数据,确保数据的完整性和一致性。编码问题一直是web开发中的一个棘手问题,希望这篇文章能够帮助大家更好地理解和应对编码相关的挑战。

相关文章:
【MySQL系列】深入理解MySQL中的存储、排序字符集
前言 在创建数据库时,我们经常会需要填写数据库的所用字符集、排序规则,字符集和排序规则是两个非常重要的概念,它们决定了数据库如何存储和比较字符串数据。在 MySQL 中,常用的存储字符集有 utf8、utf8mb4,而排序字符…...
RPC-健康检测机制
什么是健康检测? 在真实环境中服务提供方是以一个集群的方式提供服务,这对于服务调用方来说,就是一个接口会有多个服务提供方同时提供服务,调用方在每次发起请求的时候都可以拿到一个可用的连接。 健康检测,能帮助从连…...
关于Java处理Excel常规列表记录,并入库的操作
1.描述 对于常规的Excel列表(二维表格)的入库处理,一般的mysql连接工具,例如Navicat就支持。但是,因为业务需要,不想每次都去手动导入,所以这里采用编码且定时任务的形式来实现。 2.Excel常规列…...
深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解
目录 深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解 一、引言:为什么要使用Array.find() 二、Array.find()的使用与技巧 1、基础语法 2、返回值 3、使用技巧 三、Array.find()的优势与实际应用案例 1、利用返回引用…...
计算机网络安全 —— 对称加密算法 DES (一)
一、对称加密算法概念# 我们通过计算机网络传输数据时,如果无法防止他人窃听, 可以利用密码学技术将发送的数据变换成对任何不知道如何做逆变换的人都不可理解的形式, 从而保证了数据的机密性。这种变换被称为加密( encryptio…...
5. ARM_指令集
概述 分类 汇编中的符号: 指令:能够编译生成一条32位机器码,并且能被处理器识别和执行伪指令:本身不是指令,编译器可以将其替换成若干条指令伪操作:不会生成指令,只是在编译阶段告诉编译器怎…...
Jenkins的pipeline Script的 每个组件的详细讲解
在Jenkins的Pipeline脚本中,各个组件的配置和Groovy的一些常用函数起到了决定性的作用,帮助开发人员控制自动化流程的执行。以下是对Jenkins Pipeline的主要组件和Groovy常用函数的详细讲解: 1. Jenkins Pipeline主要组件 1.1 agent 功能&…...
Tomcat 和 Netty 的区别及应用场景分析
在 Java Web 开发中,Tomcat 和 Netty 都是常见的网络框架,它们各自有着不同的设计理念和适用场景。本文将通过详细的对比和实际场景示例,帮助你理解 Tomcat 和 Netty 在功能、性能、架构等方面的差异,帮助你在实际开发中做出更合理…...
6.C操作符详解,深入探索操作符与字符串处理
C操作符详解,深入探索操作符与字符串处理 C语言往期系列文章目录 往期回顾: C语言是什么?编程界的‘常青树’,它的辉煌你不可不知VS 2022 社区版C语言的安装教程,不要再卡在下载0B/s啦C语言入门:解锁基础…...
生数科技发布 Vidu 1.5 新版本,引领视频大模型新潮流
在国内视频大模型领域,生数科技一直以创新和突破而备受瞩目。近日,生数科技再度发力,发布了 Vidu 1.5 新版本,为视频创作带来了全新的变革与机遇。 Vidu 1.5 新版本在多个方面展现出了卓越的性能和创新的特点。首先,它…...
CentOS 7 aarch64停止更新后安装gcc8 —— 筑梦之路
CentOS 7.9非X86架构系统生命周期结束后(2024-6-30)配置在线可用yum源 —— 筑梦之路_centos7.9 arm-CSDN博客 以前的做法 sudo yum install centos-release-scl-rh sudo yum install devtoolset-8-buildsudo yum install devtoolset-8-gdb sudo yum i…...
WPF下 DataGrid加入序号列
先上代码: <DataGrid Name"DGV" AutoGenerateColumns"False" Grid.Row"0" Grid.Column"0" HorizontalGridLinesBrush"RoyalBlue" VerticalGridLinesBrush"Tomato" CanUserAddRows"False&qu…...
iOS UI 自动化 手势右滑退出当前页面
1、TouchAction from appium.webdriver.common.touch_action import TouchAction# 获取屏幕的宽度和高度 screen_width driver.get_window_size()["width"] screen_height driver.get_window_size()["height"]# 定义滑动的起点和终点坐标 start_x 0 en…...
《MySQL 实战教程:从零开始到高手进阶》
当然可以。下面是一篇关于MySQL的学习指南,它适合初学者到中级用户,涵盖了MySQL的基础知识、安装步骤、基本命令以及一些高级功能。 MySQL 学习指南 1. 了解 MySQL MySQL 是一个关系型数据库管理系统(RDBMS),由瑞典…...
第27天 安全开发-PHP应用TP 框架路由访问对象操作内置过滤绕过核心漏洞
时间轴 演示案例 TP 框架-开发-配置架构&路由&MVC 模型 TP 框架-安全-不安全写法&版本过滤绕过 TP 框架-开发-配置架构&路由&MVC 模型 参考: https://www.kancloud.cn/manual/thinkphp5_1 1、配置架构-导入使用 去thinkphp官网可以看到&…...
应用系统开发(12) Zync中实现数字相敏检波
在 Xilinx Zynq 系列(如 Zynq-7000 或 Zynq UltraScale+)中实现数字相敏检波(DSP,Digital Synchronous Detection)可以通过硬件(PL部分,FPGA逻辑)和软件(PS部分,ARM Cortex-A 处理器)的协同工作来实现。以下是一个详细的设计方法,包括基本原理和 Zynq 的实现步骤。…...
栈Stack和队列Queue
目录 一、栈 (1)用数组实现 (2)用单链表实现 (3)用标注尾结点的单链表实现 (4)用双向链表实现 2、栈的实际应用 (1)改变元素的序列 (2&am…...
uniapp 微信小程序地图标记点、聚合点/根据缩放重合点,根据缩放登记显示气泡marik标点
如图,如果要实现上方的效果: 上方两个效果根据经纬度标记点缩放后有重复点会添加数量 用到的文档地址https://developers.weixin.qq.com/miniprogram/dev/api/media/map/MapContext.addMarkers.htmlMapContext.addMarkers(Object object) 添加标记点Ma…...
Percona XtraBackup备份docker版本mysql 5.7
my.cnf配置文件 [client] default_character_setutf8[mysqld] # 数据存储目录(必须手动指定) datadir/var/lib/mysql/data# 字符集 collation_server utf8_general_ci character_set_server utf8 # 二进制日志 server-id1 log_bin/var/log/mysql/binl…...
C++:关联式容器的介绍及map与set的使用
我们之前已经学习过string,vector,list,queue,priority_queue等容器,这些容器我们统称为序列式容器,因为它们的数据的逻辑结构呈线性。因为这些容器中存储的数据即便二者之间发生交换,也不会对原有的容器结构造成太大影响。 但上篇文章我们介…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
