隐式类型转换导致索引失效:varchar字段传数字不加引号或int字段传字符串带引号,均触发逐行CAST/CONVERT,破坏B+树有序性,使优化器弃用索引而全表扫描,EXPLAIN显示type=ALL、key=NULL。

因为隐式类型转换会让MySQL在索引列上实际执行类似 CAST(col AS SIGNED) 或 CONVERT(col, CHAR) 的操作,破坏B+树索引的有序性,优化器只能放弃索引走全表扫描。
varchar字段传数字不加引号:索引直接失效
当查询条件是 WHERE user_id = 12345,而 user_id 是 VARCHAR 类型时,MySQL会把整行的 user_id 值全部转成数字再比对。这等价于在索引列上套了函数,B+树无法按原始字符串顺序快速定位。
-
EXPLAIN显示type=ALL、key=NULL - 响应时间从毫秒级飙升到数秒,数据量越大越明显
- MyBatis里用
${}拼接(如WHERE user_id = ${id})会丢掉引号,极易触发此问题
int字段传字符串带引号:同样索引失效
反向也成立:索引字段是 INT,但写成 WHERE id = '123',MySQL会把每一行的 id 转成字符串比较,执行计划中出现 CONVERT(id, CHAR)。
- 看似只是“加个引号”,但底层已无法复用整型索引的二分查找能力
- 尤其在高并发查询或大表JOIN中,CPU和IO开销陡增
- 别依赖ORM自动“聪明处理”——有些旧版驱动或自定义SQL拼接仍会出错
字符集/排序规则不一致导致JOIN时索引失效
两张表 JOIN 时,若关联字段字符集不同(如一张是 utf8mb4,另一张是 utf8),或排序规则冲突(如 utf8mb4_unicode_ci vs utf8mb4_general_ci),MySQL无法直接用索引做哈希匹配或归并连接。
- 退化为嵌套循环 + 每次JOIN前临时转换字段值
-
EXPLAIN中Extra字段可能出现Using where; Using join buffer - 用
SHOW CREATE TABLE确认真实字符集,别只看Java实体类或建表语句注释
最隐蔽的问题往往藏在类型“看起来一样”的地方:比如前端传参是字符串,后端没做校验就直塞SQL;或者日志脚本硬编码 status = '1',而数据库里 status 是 TINYINT。这类问题不会报错,但会在数据量上来后突然暴雷。


















