key为null而possible_keys有值且type为all或index,通常是因关联字段collation不一致导致索引被弃用;需用show full columns比对collation列,并确保@@collation_connection与之完全一致。

EXPLAIN 显示 key 为 NULL 就该查 COLLATION
只要 EXPLAIN 中被驱动表的 key 是 NULL,而 possible_keys 有值、type 是 ALL 或 index,基本就是字段排序规则(COLLATION)不一致导致的。这不是索引没建,是 MySQL 主动弃用——因为不同 COLLATION 下相同字符串可能被判定为不等,B+ 树无法保证结果正确性。
用 SHOW FULL COLUMNS 直接比对两表关联字段
别靠印象或 SHOW CREATE TABLE 猜,执行这两条命令看真实定义:
SHOW FULL COLUMNS FROM table1 LIKE 'join_col';SHOW FULL COLUMNS FROM table2 LIKE 'join_col';
重点比对输出里的 Collation 列是否**完全一致**。例如 utf8mb4_0900_as_cs 和 utf8mb4_unicode_ci 虽同属 utf8mb4 字符集,但排序逻辑不同,MySQL 视为不兼容。
别漏掉连接层的 @@collation_connection
即使两张表字段的 COLLATION 已统一,如果应用连接进来时 @@collation_connection 不匹配,SQL 中的字符串字面量(比如 'abc')仍会被按错误规则解析,JOIN 条件在解析前就失真。
- 查当前连接:
SELECT @@collation_connection; - 它必须和两个字段的
Collation完全相同,否则照样触发隐式转换 - 主从环境还要单独查复制线程:
SELECT @@collation_connection;在从库执行,不是看应用连接
information_schema.COLUMNS 可批量核对多个字段
当涉及多张表、多个关联列时,一条 SQL 比对更高效:
SELECT table_name, column_name, character_set_name, collation_name
FROM information_schema.COLUMNS
WHERE table_name IN ('t1', 't2')
AND column_name IN ('user_id', 'email');
注意:只看 collation_name —— 即使 character_set_name 都是 utf8mb4,只要 collation_name 不同,索引就失效。这个值才是 MySQL 实际做等值比较时依赖的依据。
最容易被忽略的是:字段定义改对了,@@collation_connection 还是旧的;或者应用代码里用了 ${} 拼接字符串,导致引号丢失,MySQL 把 VARCHAR 当数字转,连 COLLATION 都没机会参与比较。











