use index是优化器建议,可能被无视;force index强制使用索引但有性能风险;ignore index屏蔽指定索引;三者均需通过explain验证效果。

use index 是建议,不是命令
use index 告诉 MySQL:“这几个索引你优先考虑一下”,但它完全可能被优化器无视——尤其是当它算出来全表扫描更快时。比如你写 SELECT * FROM users USE INDEX (idx_age) WHERE country = 'CN',而 idx_age 根本不包含 country 字段,MySQL 就会直接跳过它,甚至可能退化成全表扫描。
- 只对当前查询生效,不影响索引本身或后续语句
- 适用于你怀疑优化器“没看到好索引”,但又不想强拧它的时候
- 不能指定不存在的索引名,否则报错
ERROR 1176: Key 'xxx' doesn't exist in table - 复合索引必须严格匹配最左前缀,
USE INDEX (idx_name_email)对WHERE email = 'a@b.com'无效
force index 是硬性要求,带代价
force index 的意思是:“不管统计信息、行数估算、成本模型怎么算,都给我用这个索引”。它能绕过优化器误判(比如小表误判为大表、索引选择率估算偏差),但也可能把性能拖垮——比如强制用一个低选择性的索引去查 90% 的数据。
- 一旦用了
FORCE INDEX,即使该索引根本无法过滤 WHERE 条件,MySQL 也会先走索引再回表(或全扫描索引),不会 fallback 到全表扫描 - 常见于临时调试:发现某条慢查突然不用了原本高效的索引,加
FORCE INDEX快速验证是否是优化器 bug 或统计信息过期 - 上线前务必测试执行计划:
EXPLAIN FORMAT=TREE看是否真走了指定索引,以及是否引发大量回表
ignore index 是“屏蔽干扰项”的手术刀
当你有多个相似索引(比如 idx_country 和 idx_country_status),而优化器总选错那个窄但低效的,IGNORE INDEX 就是最快捷的干预方式。它不帮你选哪个好,只是把明显不该参与竞争的索引“拉黑”。
- 典型场景:给
status加了单列索引后,优化器开始放弃更优的复合索引idx_country_created_at,此时加IGNORE INDEX (idx_status)让它回归理性 - 可一次忽略多个:
IGNORE INDEX (idx_age, idx_email) - 注意:如果忽略的是唯一索引或主键,且查询条件恰好依赖它(如
WHERE id = ?),MySQL 会报错或降级为全表扫描——它没法绕开主键找数据
别忘了看执行计划,否则全是白忙
所有 USE/FORCE/IGNORE 提示的效果,必须通过 EXPLAIN 验证。MySQL 8.0+ 推荐用 EXPLAIN FORMAT=TREE,能清晰看到是否命中索引、是否触发回表、是否用了你指定的索引。
- 执行计划里出现
Using where; Using index才算真正用上覆盖索引;若只有Using where,大概率在回表 - 加了提示后
rows估算值反而变大?说明提示起反作用,赶紧撤掉 - 线上环境慎用
FORCE INDEX:统计信息更新、数据分布变化、版本升级都可能导致它从“救命稻草”变成“性能炸弹”
真正难的从来不是加不加提示,而是判断优化器为什么选错——是统计信息不准?还是隐式类型转换让索引失效?提示只是止痛片,不是诊断书。










