MySQL 8.0.3起彻底移除查询缓存,5.7默认禁用且存在并发锁问题;替代方案为应用层或代理层缓存;EXPLAIN中需重点关注type(非ALL)和key(非空),并避免隐式转换、OR、左模糊等索引失效场景。

MySQL 8.0 之后查询缓存已被移除,别再配 query_cache_type
MySQL 官方从 8.0.3 版本起彻底删除了查询缓存(Query Cache)模块。如果你在配置文件里还写着 query_cache_type=1 或调用 SQL_CACHE 提示符,MySQL 启动会报警告,语句也会被静默忽略。
- 5.7 是最后一个支持查询缓存的大版本,但默认已禁用(
query_cache_type=0),且存在严重并发锁争用问题 - 即使开启,只要表有任意写操作(
INSERT/UPDATE/DELETE),该表所有缓存结果都会被清空,实际命中率极低 - 替代方案是应用层缓存(如 Redis)或代理层缓存(如 ProxySQL 的 result cache),它们可控性更强、粒度更细
EXPLAIN 看懂索引是否生效,重点盯 type 和 key 字段
执行 EXPLAIN SELECT ... 是判断索引是否走对的第一步。真正关键的不是有没有 key,而是 type 值是否为 range、ref、eq_ref;如果出现 ALL,基本等于全表扫描。
-
key为空:没走索引,可能原因包括字段没建索引、用了函数(如WHERE YEAR(created_at) = 2023)、隐式类型转换(如字符串字段查数字: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+ 树索引的固有限制。
2088shop商城购物系统是商城系统中功能最全的一个版本:非会员购物、商品无限级分类、不限商品数量、商品多级会员定价、上货库存、Word在线编辑器、订单详情销售报表、商品评论、留言簿、管理员多级别、VIP积分、会员注册积分奖励、智能新闻发布、滚动公告、投票调查、背景图片颜色更换、店标上传、版权联系方式修改、背景音乐(好歌不断)、广告图片支持Flash、弹出浮动广告、搜索引擎关健词优化、图文友情联
-
WHERE mobile = 13800138000→ 如果mobile是VARCHAR,会转成数字比较,触发全表扫描;应统一写成字符串:'13800138000' -
WHERE status = 'active' OR type = 'vip'→ 即使两字段都有索引,OR通常导致放弃索引走全表;改用UNION或确保其中一个条件能走强索引 -
WHERE name LIKE '%张%'→ 左模糊无法使用 B+ 树的有序性;如必须模糊搜索,考虑全文索引(FULLTEXT)或 Elasticsearch
EXPLAIN SELECT id, name FROM users WHERE name LIKE '张%';
这句能走索引;但把 '张%' 换成 '%张',type 就变成 ALL。
索引不是越多越好,也不是建了就一定生效。真正卡住性能的,往往是那条没走索引的慢查询,藏在凌晨三点的监控告警里,而不是文档开头的“最佳实践”列表中。









