MySQL 8.0.3起彻底移除查询缓存,5.7默认禁用且存在并发锁问题;替代方案为应用层或代理层缓存;EXPLAIN中需重点关注type(非ALL)和key(非空),并避免隐式转换、OR、左模糊等索引失效场景。
query_cache_type
MySQL 官方从 8.0.3 版本起彻底删除了查询缓存(Query Cache)模块。如果你在配置文件里还写着 query_cache_type=1 或调用 SQL_CACHE 提示符,MySQL 启动会报警告,语句也会被静默忽略。
query_cache_type=0),且存在严重并发锁争用问题INSERT/UPDATE/DELETE),该表所有缓存结果都会被清空,实际命中率极低EXPLAIN 看懂索引是否生效,重点盯 type 和 key 字段执行 EXPLAIN SELECT ... 是判断索引是否走对的第一步。真正关键的不是有没有 key,而是 type 值是否为 range、ref、eq_ref;如果出现 ALL,基本等于全表扫描。
key 为空:没走索引,可能原因包括字段没建索引、用了函数(如 WHERE YEAR(created_at) = 2025)、隐式类型转换(如字符串字段查数字:WHERE status = 1,而 status 是 VARCHAR)Extra 出现 Using filesort 或 Using temporary:ORDER BY 或 GROUP BY 无法利用索引完成,需要优化排序字段或加覆盖索引(a,b,c) 索引,WHERE b = ? 不会命中;但 WHERE a = ? AND b > ? 可以用到前两列当 SELECT 的所有字段都包含在索引中时,MySQL 直接从 B+ 树叶子节点取值,无需回主键索引查数据行——这就是覆盖索引。它减少 I/O,提升速度,但设计不当反而拖慢写入和占用空间。
SELECT user_id, action, created_at FROM log WHERE app_id = ? ORDER BY created_at DESC LIMIT 20,可建 (app_id, created_at, user_id, action)
TEXT、长 VARCHAR)塞进索引;索引本身变重,插入/更新变慢,缓冲池压力上升SELECT * 在主键查询下天然“覆盖”,但非主键索引必须显式包含所有 SELECT 字段才生效OR、LIKE 左模糊很多 SQL 看似合理,却因细节触发索引失效。这些不是 bug,是 B+ 树索引的固有限制。
WHERE mobile = 13800138000 → 如果 mobile 是 VARCHAR,会转成数字比较,触发全表扫描;应统一写成字符串:'13800138000'
WHERE status = 'active' OR type = 'vip' → 即使两字段都有索引,OR 通常导致放弃索引走全表;改用 UNION 或确保其中一个条件能走强索引WHERE name LIKE '%张%' → 左模糊无法使用 B+ 树的有序性;如必须模糊搜索,考虑全文索引(FULLTEXT)或 ElasticsearchEXPLAIN SELECT id, name FROM users WHERE name LIKE '张%';
这句能走索引;但把 '张%' 换成 '%张',type 就变成 ALL。
索引不是越多越好,也不是建了就一定生效。真正卡住性能的,往往是那条没走索引的慢查询,藏在凌晨三点的监控告警里,而不是文档开头的“最佳实践”列表中。