同事问我 MySQL 用啥排序规则,我差点答不上来

前几天,我在建数据库的时候,同事刚好在我旁边,他问我:"你建库一般用什么排序规则,怎么感觉都一样啊!"。

本来我还想装一下的,可发现我越讲越不对,赶紧去搜了一下相关知识,这可终于整明白了。

下面给大家分享一下。

什么是排序规则(Collation)?

简单说:排序规则决定了 MySQL 怎么"看"字符串。

比如:

  • 它认为 'A''a' 是一样的吗?
  • 它觉得 'é''e' 要不要区分?
  • 中文字符按什么顺序排?

Collation(排序规则) 就是解决这些问题的。

排序规则长什么样?

MySQL 的排序规则名字通常像这样:

复制代码
utf8mb4_0900_ai_ci
utf8mb4_general_ci
utf8mb4_bin

如下图:

我们拆开来看:

部分 含义
utf8mb4 字符集(支持 emoji、中文、英文等所有 Unicode 字符)
0900 基于 Unicode 9.0.0 标准(MySQL 8.0+ 新特性)
ai / as Accent Insensitive(不区分重音) / Accent Sensitive(区分重音)
ci / cs Case Insensitive(不区分大小写) / Case Sensitive(区分大小写)
bin Binary(二进制比较,最严格)

举个栗子:不同排序规则的区别

我们创建三个表,分别用不同的排序规则,看看效果:

场景1:大小写敏感吗?

sql 复制代码
-- 表1:使用 utf8mb4_0900_ai_ci(默认,不区分大小写)
CREATE TABLE users_ci (
  name VARCHAR(50)
) COLLATE utf8mb4_0900_ai_ci;

INSERT INTO users_ci VALUES ('Alice'), ('alice');

-- 查询
SELECT * FROM users_ci WHERE name = 'ALICE';
-- 结果:返回 Alice 和 alice(因为不区分大小写)
sql 复制代码
-- 表2:使用 utf8mb4_bin(区分大小写)
CREATE TABLE users_bin (
  name VARCHAR(50)
) COLLATE utf8mb4_bin;

INSERT INTO users_bin VALUES ('Alice'), ('alice');

SELECT * FROM users_bin WHERE name = 'ALICE';
-- 结果:空!因为 'ALICE' ≠ 'Alice' ≠ 'alice'

结论_ci 不区分大小写,_bin 区分。


场景2:重音符号要不要管?

比如法语中的 cafécafe

  • _ai(Accent Insensitive)规则下:café = cafe
  • _as_bin 规则下:café ≠ cafe

MySQL 8.0+ 支持更精细的控制,比如:

sql 复制代码
utf8mb4_0900_as_cs  -- 区分大小写 + 区分重音
utf8mb4_0900_ai_ci  -- 不区分大小写 + 不区分重音(默认)

场景3:中文排序乱序?

如果你用 utf8mb4_general_ci 排中文,可能会发现:

sql 复制代码
SELECT name FROM users ORDER BY name;
-- 结果:张三、李四、王五......顺序看起来"不对"

这是因为 general_ci 是一种简化的排序算法,它为了速度牺牲了准确性。

正确做法 :用 utf8mb4_unicode_ci 或更好的 utf8mb4_0900_ai_ci(MySQL 8.0 默认),它们基于 Unicode 标准,对中文、日文、韩文等支持更好。


主要区别维度


1. 大小写敏感性(Case Sensitivity)

  • _ci :Case Insensitive(不区分大小写)
    • 例如:utf8_general_ci'A' = 'a'
  • _cs_bin :Case Sensitive(区分大小写)
    • utf8_binutf8mb4_0900_cs'A' ≠ 'a'

注意:_cs(Case Sensitive)在旧版本中较少见,MySQL 8.0 引入了更标准的命名如 utf8mb4_0900_cs


2. 重音符号敏感性(Accent Sensitivity)

  • _ai:Accent Insensitive(不区分重音)
  • _as:Accent Sensitive(区分重音)

在 MySQL 8.0+ 中,部分排序规则支持 _as/_ai,例如 utf8mb4_0900_as_cs 表示既区分大小写又区分重音。


3. 二进制排序(Binary Collation)

  • _bin 结尾(如 utf8mb4_bin
  • 按照字符的二进制值(字节值)进行比较,严格区分大小写、重音、编码顺序
  • 不使用语言规则,速度较快但不符合人类语言习惯

4. 语言/区域特定排序

某些排序规则针对特定语言优化:

  • utf8mb4_spanish_ci:西班牙语排序(如 ñ 排在 n 之后)
  • utf8mb4_german2_ci:德语电话簿排序规则
  • utf8mb4_ja_0900_as_cs:日语排序(需 MySQL 8.0+)

5. Unicode 版本差异(MySQL 8.0+)

MySQL 8.0 默认使用基于 Unicode 9.0 的排序规则(如 utf8mb4_0900_ai_ci):

  • 更准确的多语言支持
  • 更好的性能(相比旧的 utf8mb4_general_ci
  • 0900 表示基于 Unicode 9.0.0

对比:

  • utf8mb4_general_ci:旧版,速度快但排序不准确(如认为 'ö' = 'o'
  • utf8mb4_unicode_ci:基于 Unicode 4.0,较准确
  • utf8mb4_0900_ai_ci:MySQL 8.0 默认,基于 Unicode 9.0,更准确高效

常见排序规则对比示例

排序规则 大小写敏感 重音敏感 说明
utf8mb4_general_ci 旧版通用,速度快但不准
utf8mb4_unicode_ci 基于 Unicode 4.0,较准确
utf8mb4_0900_ai_ci MySQL 8.0 默认,基于 Unicode 9.0
utf8mb4_0900_as_cs 区分大小写和重音
utf8mb4_bin 二进制比较,最快但最"机械"

如何查看可用排序规则?

sql 复制代码
SHOW COLLATION LIKE 'utf8mb4%';

如何设置排序规则?

数据库级:

sql 复制代码
CREATE DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

表级:

sql 复制代码
CREATE TABLE t (name VARCHAR(100)) COLLATE utf8mb4_bin;

列级:

sql 复制代码
name VARCHAR(100) COLLATE utf8mb4_0900_as_cs

查询时临时指定:

sql 复制代码
SELECT * FROM t ORDER BY name COLLATE utf8mb4_bin;

实际建议

  • 一般应用 :使用 utf8mb4_0900_ai_ci(MySQL 8.0+)或 utf8mb4_unicode_ci(旧版本)
  • 需要区分大小写 :用 utf8mb4_0900_as_csutf8mb4_bin
  • 性能敏感且无需语言规则 :用 _bin
  • 避免使用 utf8mb4_general_ci(除非兼容旧系统),因其排序逻辑不准确

总结

  • 排序规则 = 字符串的"比较规则"
  • _ci = 不区分大小写,_cs/_bin = 区分
  • MySQL 8.0 默认的 utf8mb4_0900_ai_ci 是目前最推荐的选择
  • 中文、多语言项目不要用 general_ci,它已经过时了
  • 用户名、密码等关键字段,建议用区分大小写的规则

本文首发于公众号:程序员刘大华,专注分享前后端开发的实战笔记。关注我,少走弯路,一起进步!

📌往期精彩

《前端高手才知道的秘密:Blob 居然这么强大》

《这 5 个冷门 HTML 标签,让我直接删了100 行 JS 代码》

《重构了20个SpringBoot项目后,总结出这套稳定高效的架构设计》

《代码里全是 new 对象,真的很 Low 吗?我认真想了一晚》

相关推荐
程序员阿明14 小时前
spring boot 3.5+flowable7+java 21流程引擎测试程序
java·spring boot·后端
不会c嘎嘎14 小时前
mysql -- 使用CAPI访问mysql服务器
服务器·数据库·mysql
粟悟饭&龟波功14 小时前
【软考系统架构设计师】九、架构演化与维护
前端·后端·架构·系统架构·软件工程
Zzzzmo_14 小时前
【MySQL】数据类型 及 表的操作
数据库·mysql
冷雨夜中漫步14 小时前
Spring Cloud入门—— (1)Spring Cloud Alibaba生态组件Nacos3.0本地部署
后端·spring·spring cloud
L16247614 小时前
linux系统中YUM安装MySQL数据库详细教程
linux·数据库·mysql
superman超哥14 小时前
Rust API 设计的零成本抽象原则:性能与表达力的完美统一
开发语言·后端·rust·rust api·抽象原则·性能与表达力
残风也想永存14 小时前
【MySQL】事务管理
数据库·mysql
superman超哥14 小时前
Rust 所有权的三大基本规则:内存安全的类型系统基石
开发语言·后端·rust·内存安全·rust所有权·基本规则·系统基石