日志里同一条 SQL 两次执行差了 200 倍,一次是 WHERE phone = '13800138000',一次是 WHERE phone = 13800138000。后者 explain 里的 key 是 NULL。乍看像缓存或者权限的锅,追下去往往不是。
EXPLAIN SELECT id FROM users WHERE phone = '13800138000'; SHOW WARNINGS;
追下去是这么回事:phone 列是 varchar,传入整数常量时数据库把字符串列整体转成 double 再比较,转换后的值不再有序,索引上的统计信息也用不上。转换发生在列这一侧,代价按行数算。
「隐式类型转换」这类改动最怕改一半,回滚脚本先准备好,再动生产。一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。
先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。别只看报错的最后一行,往上看几行,真正的起因通常在上面。
具体做法是,先把调用方传参统一成字符串 不要在 DAO 层拼数字;用 explain 看 key 是否为空 确认转换发生在哪一侧;在参数绑定处加类型校验 拦住被当成 int 传下去的值;存量 SQL 从慢查询日志里捞 一条条改。
验收就看一点,换成带引号的参数后 key 显示 idx_phone type 变成 ref 耗时回到个位数毫秒。
