快速确认collation是否一致需查字段定义而非数据库默认值,用show full columns或information_schema.columns比对collation列值,join失效时两边collation_name必须完全相同,且连接层@@collation_connection须与字段collation对齐。

直接改字段的 COLLATION,别只改 CHARACTER SET;只要 EXPLAIN 显示 type: ALL 或 key: NULL,但单表查得快,八成是这个原因。
怎么快速确认是不是 COLLATION 不一致?
别看 SHOW CREATE DATABASE 里的默认值——它不影响已有字段。真正起作用的是字段定义里写的那部分。
- 用
SHOW FULL COLUMNS FROM t1 LIKE 'user_id'查Collation列值,注意utf8mb4_0900_as_cs和utf8mb4_unicode_ci虽同属 utf8mb4,但不可比 - 更稳妥:查
INFORMATION_SCHEMA.COLUMNS,一次性比对多张表:SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'your_db' AND TABLE_NAME IN ('t1', 't2') AND COLUMN_NAME IN ('uid', 'ref_id'); - JOIN 失效时,两边字段的
COLLATION_NAME必须完全一致;哪怕都是utf8mb4,只要排序规则不同,MySQL 就会放弃索引
ALTER TABLE 改 COLLATION 的正确写法
只写 MODIFY COLUMN name VARCHAR(50) CHARACTER SET utf8mb4 是无效操作——它不会改 COLLATE,而 MySQL 比较时实际依赖的是排序规则。
- 必须显式带上目标
COLLATE,且值要和关联字段完全一致:ALTER TABLE t2 MODIFY uid VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs;
- 先用
SHOW FULL COLUMNS确认当前COLLATION_NAME,再选匹配项,别硬套utf8mb4_unicode_ci - 字段有索引时,
MODIFY会重建索引;大表务必低峰期操作,否则锁表时间长 - 含外键或全文索引的表,
MODIFY可能失败,需提前DROP FOREIGN KEY或处理约束
为什么改完表结构查询还是慢?
因为连接层的 @@collation_connection 没对齐。就算字段全统一了,如果应用连上来时用的是 utf8mb4_general_ci,而字段是 utf8mb4_0900_as_cs,MySQL 仍会在解析 WHERE name = 'xxx' 时做隐式转换,索引照样失效。
- JDBC 连接串加:
?useUnicode=true&characterEncoding=utf8mb4&collationConnection=utf8mb4_0900_as_cs - PHP mysqli 连接后执行:
mysqli_set_charset($conn, 'utf8mb4'),再执行SET NAMES utf8mb4 COLLATE utf8mb4_0900_as_cs - 验证是否生效:
SELECT @@collation_connection,返回值应与字段COLLATION_NAME完全一致 - 漏掉
collation=这部分,前面所有表和字段改得再整齐,查询时仍可能触发转换
最易被忽略的是存储过程里传参:比如 NAME_CONST('v_id', _utf8mb4'xxx' COLLATE utf8mb4_unicode_ci),如果对应列实际是 utf8mb4_0900_as_cs,优化器立刻放弃索引。安全写法只有省略 COLLATE,让 MySQL 自动按列定义推导。











