慢查询排查时,看执行计划是标准动作。但有一类问题执行计划看不出来——隐式类型转换导致的索引失效,往往表现为「明明有索引却走了全表扫」。
场景一:字符串列传了数字
字段是 varchar,查询写 where phone = 13800138000(不加引号)。MySQL 会把列转成数字再比较,索引直接失效。这个坑在手机号、订单号、身份证这类「看起来像数字」的字段上最常见。
场景二:字符集不一致的关联
两张表 JOIN,一个是 utf8mb4,一个是 utf8(或者一个 utf8mb4_general_ci,一个 utf8mb4_unicode_ci)。关联字段的字符集或排序规则不同,JOIN 时无法用索引,会退化成嵌套循环全扫。跨国系统、历史遗留库迁移之后特别容易踩。
场景三:函数包裹索引列
where date(create_time) = '2026-10-30',或者 where upper(name) = 'ABC'。函数作用在列上,索引就用不上。改成范围查询:create_time >= '2026-10-30' and create_time < '2026-10-31'。如果确实需要函数查询,建函数索引或者生成列。
怎么系统性地查
一是打开慢查询日志,按「扫描行数 / 返回行数」的比值排序,比值大的优先看。二是用 explain 的 filtered 和 rows 两个字段交叉判断,rows 巨大但 filtered 很低,基本就是索引没生效。三是写一条对照查询,把参数类型改对,看执行计划有没有变化——这是最快的验证方式。
审核清单上该加的一条
SQL 上线前,除了看有没有索引,还要看「索引列和查询参数的类型是否严格一致」。这一条能拦掉相当一部分线上慢查询。
本文由奇幻维度内容助手整理发布,欢迎在评论区交流你的看法。