
MySQL 什么时候必须用 IGNORE INDEX
不是“想忽略就忽略”,而是当优化器选错索引、导致查询变慢甚至卡死时,才需要人工干预。典型场景是:表有多个复合索引,WHERE 条件覆盖了多个字段,但 MySQL 选了区分度低的前缀字段索引,或者选了包含大量重复值的列作为驱动索引。
常见错误现象:EXPLAIN 显示 key 列非空但 rows 高得离谱(比如几十万),实际结果只返回几条;或 type 是 range 却比全表扫描还慢。
- 只在确认
EXPLAIN结果异常且已排除统计信息过期(ANALYZE TABLE)后使用 - 不能用于主键或唯一索引被强制跳过后的语义错误场景(比如
WHERE id = ?却IGNORE INDEX (PRIMARY),会退化成全表扫,且无法利用主键约束) -
IGNORE INDEX是语句级提示,不改变表结构,也不影响其他查询
IGNORE INDEX 的写法和生效范围
语法必须紧贴 FROM 子句,位置错了直接报错或静默失效。它只对当前 SELECT(或 UPDATE/DELETE)生效,不能跨子查询继承。
错误写法示例:SELECT * FROM t1 IGNORE INDEX (idx_a) WHERE a=1 —— 缺少 USING 或 FOR JOIN 关键字,MySQL 5.7+ 会报 ERROR 1064。
- 基本格式:
SELECT * FROM t1 IGNORE INDEX (idx_name) WHERE ... - 多索引忽略:
IGNORE INDEX (idx_a, idx_b),括号内用英文逗号分隔,无空格要求但建议统一 - 指定索引类型无效:
IGNORE INDEX USING HASH (...)不合法,MySQL 不支持按类型忽略 - 别名表必须在
FROM后立即写提示:SELECT * FROM t1 AS a IGNORE INDEX (idx_a) WHERE a.x = 1
为什么 FORCE INDEX 有时比 IGNORE INDEX 更安全
IGNORE INDEX 是“减法思维”——告诉优化器“别用这几个”,但没说“该用哪个”。如果剩下可用索引都不合适,它可能 fallback 到全表扫描,而你完全没感知。
对比来看:FORCE INDEX (idx_c) 是“加法思维”,明确指定路径,只要该索引能覆盖查询条件,就能稳定走索引扫描。
- 当已有明确更优索引时,优先用
FORCE INDEX,避免“忽略后无路可走” -
IGNORE INDEX更适合调试阶段:先禁掉可疑索引,看EXPLAIN是否转向预期索引 - 注意兼容性:
FORCE INDEX在 MySQL 5.0+ 全版本支持;IGNORE INDEX从 5.1 开始支持,但早期版本行为略有差异(如 5.1.12 前不支持多索引列表) - 分区表中,
IGNORE INDEX对全局二级索引有效,但对分区键上的本地索引需额外验证是否真正跳过
容易被忽略的坑:提示不生效的三种情况
写了 IGNORE INDEX 却发现执行计划没变?大概率掉进这三个坑里。
- 索引名写错或大小写不匹配:MySQL 在默认配置下索引名大小写敏感(尤其在 Linux 文件系统上),
IGNORE INDEX (IDX_A)和实际索引名idx_a不等价 - 查询涉及隐式类型转换:比如
WHERE varchar_col = 123,MySQL 会放弃所有索引(包括被IGNORE的),此时提示根本没机会起作用 - 优化器判定“即使忽略也无索引可用”:例如只有一条索引且被
IGNORE,又没覆盖全部WHERE字段,它会直接走全表扫描,且EXPLAIN的key列显示NULL,看起来像提示失效
真正难处理的是第三种——它意味着你得先确认“有没有其他可用索引”,而不是盯着提示本身调。










