mysql 8.0默认collation为utf8mb4_0900_ai_ci,性能瓶颈主因是字段/join/函数间collation混用导致隐式转换,引发索引失效、filesort或全表扫描,而非该collation本身慢。

MySQL 8.0 的默认 collation(utf8mb4_0900_ai_ci)本身性能不差,但“默认”二字恰恰是性能隐患的起点——它不匹配你的字段定义、不统一 JOIN 条件、不贴合查询模式,这才是拖慢排序的真实原因。
为什么 ORDER BY 突然变慢了?不是 collation 本身慢,而是隐式转换在捣鬼
MySQL 8.0 默认用 utf8mb4_0900_ai_ci,但如果你的表或字段还留着 utf8mb4_general_ci 或 utf8mb4_unicode_ci,只要一执行 ORDER BY、JOIN 或 FIND_IN_SET(),就会触发 Illegal mix of collations 错误,或者更隐蔽地:MySQL 自动加 CONVERT() 隐式转换,导致无法走索引、强制 filesort、甚至全表扫描。
- 查字段真实 collation:
SHOW FULL COLUMNS FROM your_table,看Collation列是否混用 - 查 JOIN 中两边字段 collation 是否一致:
SELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME IN ('t1','t2') AND COLUMN_NAME = 'join_col' - 函数返回值 collation 常被忽略:比如
UPPER(name)在utf8mb4_0900_ai_ci库下返回的是utf8mb4_0900_as_cs,和字段 collation 冲突
改 collation-server 不解决性能问题,反而误导排查方向
SET GLOBAL collation_server = 'utf8mb4_unicode_ci' 在 MySQL 8.0+ 直接报错:Variable 'collation_server' is a read only variable。即使你改了配置文件重启,它也只影响新连接初始化时的默认值,**完全不决定新建库/表的 collation,更不影响已有字段行为**。
- 真正控制新建对象默认 collation 的是
character_set_server,且它硬编码绑定utf8mb4_0900_ai_ci—— 你配了collation-server = utf8mb4_unicode_ci,CREATE DATABASE还是生成utf8mb4_0900_ai_ci - 试图靠改这个变量来“统一 collation”是白忙:它既不修复已有字段,也不阻止 JOIN 时的隐式转换,性能瓶颈照旧
- 查当前生效值:
SELECT @@collation_server, @@collation_database, @@collation_connection,三者不同就埋雷
真正提升 ORDER BY 性能的 collation 操作,只发生在字段和索引层
排序快不快,取决于 MySQL 能不能用索引完成排序(Using index),而不是“用了哪个 collation”。而能否用索引,关键看 ORDER BY 字段的 collation 是否与索引定义一致,且无隐式转换干扰。
- 字段 collation 必须显式对齐:比如要按
name排序,就执行ALTER TABLE users MODIFY name VARCHAR(255) COLLATE utf8mb4_0900_ai_ci(别用CONVERT TO,它会重写整表) - 联合索引必须匹配排序规则:如果
ORDER BY status DESC, created_at DESC,就建INDEX idx_status_created (status, created_at) COLLATE utf8mb4_0900_ai_ci(注意:索引本身不存 collation,但字段定义必须一致) - 避免在
ORDER BY中用函数或COLLATE强转:ORDER BY name COLLATE utf8mb4_unicode_ci会导致索引失效,哪怕字段本就是那个 collation
升级后 ORDER BY 结果“乱序”,本质是排序确定性缺失,不是 collation 选错了
MySQL 8.0 废弃了老版本中对相等值的“稳定排序”保证。当多行 created_at 值相同,又没加二级排序字段时,ORDER BY created_at DESC LIMIT 20,10 可能在不同执行中返回不同顺序——这不是 bug,是设计变更。
- 解决方案不是换 collation,而是补唯一性:用
ORDER BY created_at DESC, id DESC,并确保(created_at, id)有联合索引 - 字符集混合加剧“乱序”:比如
utf8mb4_0900_ai_ci字段和utf8mb4_bin字段 JOIN 后ORDER BY,MySQL 可能随机选一个 collation 做归一化,结果不可预测 - 分页场景务必检查执行计划:
EXPLAIN SELECT ... ORDER BY x LIMIT y,确认Extra列没有Using filesort或Using temporary
最常被跳过的动作:不查字段 collation 就改配置,不看执行计划就调参数,不加二级排序就信誓旦旦说“ORDER BY 没问题”。collation 优化不是设个全局值,而是逐字段对齐、逐查询验证、逐索引校准。











