mysql查询优化中缓存与索引的结合应用

发布时间 - 2026-01-30 00:00:00    点击率:
MySQL 8.0 已彻底移除查询缓存(query_cache),仅保留 innodb_buffer_pool 缓存数据页和索引页;联合索引遵循“连续等值+最多一个范围”原则;覆盖索引可避免回表但需避开 SELECT * 和大字段陷阱;buffer pool 大小需根据命中率与物理读频率合理配置。

MySQL 查询缓存(query_cache)在 8.0 中已彻底移除,别再配置它

MySQL 5.7 是最后一个支持 query_cache_typequery_cache_size 的正式版本;8.0 起这些变量已被删除,强行设置会报错 Unknown system variable 'query_cache_type'。如果你还在查文档配 query_cache,说明你用的是过时资料或降级环境。

真实场景中,靠查询缓存提升性能的思路早已失效:它只对完全相同的 SQL 文本(含空格、大小写、库名)生效,且只要表有任意 DML 操作,整个表相关缓存全失效。高并发更新下,命中率极低,反而增加锁争用。

  • 替代方案是应用层缓存(如 Redis)或代理层缓存(如 ProxySQL 的 query cache)
  • 如果必须用 MySQL 内置缓存机制,唯一可用的是 innodb_buffer_pool —— 它缓存的是数据页和索引页,不是 SQL 结果
  • 检查是否误启用了旧配置:运行 SHOW VARIABLES LIKE 'query_cache%';,8.0 返回空结果即正常

索引不是越多越好,联合索引顺序决定能否走索引

WHERE 条件里写了 a = 1 AND b > 10 AND c = 5,但只有 (a, c, b) 索引,b > 10 就无法做索引范围扫描,因为 c = 5 是等值,但位置在 b 前面,导致 b 之后的字段无法参与范围查找。

联合索引遵循“最左前缀原则”,但更准确的理解是“连续等值 + 最多一个范围”:

  • 索引 (a, b, c) 可用于:a = 1 AND b = 2 AND c > 3(c 是最后一个,可范围)
  • 不可用于:a = 1 AND c = 3(跳过了 b,中断最左连续)
  • 可部分用于:a IN (1,2) AND b = 3(MySQL 5.7+ 支持多值等号后的字段继续走索引)
  • EXPLAINkey_len 值,能反推出实际用了索引的前几列

覆盖索引减少回表,但要注意 SELECT * 和大字段陷阱

SELECT 的所有字段都在索引中(比如索引是 (user_id, status, created_at),而语句是 SELECT user_id, status FROM orders WHERE user_id = 123),InnoDB 就不必回主键聚簇索引取整行,直接从二级索引叶子节点返回结果 —— 这就是覆盖索引。

但两个常见坑容易被忽略:

  • SELECT * 几乎不可能走覆盖索引,除非你建的索引包含所有列(不现实,且极大拖慢写入)
  • 哪怕只选几个字段,如果其中一个是 TEXTVARCHAR(2000),InnoDB 可能放弃使用该索引,因为单条索引记录过大,B+ 树效率下降
  • EXPLAINExtra 列:出现 Using index 表示走了覆盖索引;出现 Using where; Using index 是覆盖索引 + 索引条件下过滤;出现 Using filesortUsing temporary 通常意味着优化空间很大

Buffer Pool 大小与脏页刷盘节奏直接影响查询延迟

innodb_buffer_pool_size 不是越大越好,也不是设成物理内存 70% 就万事大吉。它影响三件事:热数据驻留能力、脏页堆积量、刷脏频率。

典型问题场景:

  • Buff

    er Pool 太小 → 频繁物理读 → SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads'; 持续上升
  • Buffer Pool 太大(尤其在小内存机器上)→ 操作系统开始 swap → 查询偶发卡顿几十秒,vmstat 1 可见 si/so 非零
  • 脏页太多 + 刷盘慢 → innodb_io_capacityinnodb_io_capacity_max 设太低 → 日志写满触发同步刷脏,查询突然变慢

建议用如下方式粗估初始值:

SELECT
  ROUND((SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'innodb_buffer_pool_size') / 1024 / 1024 / 1024, 2) AS pool_gb,
  ROUND((SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests') / 
        (SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads'), 2) AS hit_ratio;

命中率低于 95%,且 Innodb_buffer_pool_reads 每秒 > 10 次,才值得调大 buffer pool。

索引设计要贴着查询写,缓存得看清楚是哪一层的缓存 —— MySQL 8.0 里已经没有“查询缓存”这个东西了,别被老教程带偏。


# mysql  # redis  # 操作系统  # ai  # proxy  # red  # sql  # select  #   # using  # 并发  # 的是  # 最多  # 越好  # 移除  # 几个  # 如果你  # 太多  # 走了  # 都在  # 还在 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 东莞市网站制作公司有哪些,东莞找工作用什么网站好?  标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析  JavaScript实现Fly Bird小游戏  Linux系统命令中tree命令详解  ChatGPT常用指令模板大全 新手快速上手的万能Prompt合集  jQuery 常见小例汇总  深圳网站制作的公司有哪些,dido官方网站?  如何在新浪SAE免费搭建个人博客?  Laravel怎么返回JSON格式数据_Laravel API资源Response响应格式化【技巧】  什么是javascript作用域_全局和局部作用域有什么区别?  Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】  Linux虚拟化技术教程_KVMQEMU虚拟机安装与调优  如何在万网开始建站?分步指南解析  html5如何实现懒加载图片_ intersectionobserver api用法【教程】  Laravel怎么实现支付功能_Laravel集成支付宝微信支付  如何快速生成可下载的建站源码工具?  如何快速生成高效建站系统源代码?  如何快速登录WAP自助建站平台?  详解MySQL数据库的安装与密码配置  ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】  Laravel如何发送系统通知?(Notification渠道示例)  如何在IIS服务器上快速部署高效网站?  Laravel如何编写单元测试和功能测试?(PHPUnit示例)  如何在万网主机上快速搭建网站?  JS经典正则表达式笔试题汇总  原生JS实现图片轮播切换效果  如何用VPS主机快速搭建个人网站?  html文件怎么打开证书错误_https协议的html打开提示不安全【指南】  如何在搬瓦工VPS快速搭建网站?  Laravel如何实现多语言支持_Laravel本地化与国际化(i18n)配置教程  Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】  佛山企业网站制作公司有哪些,沟通100网上服务官网?  如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?  魔毅自助建站系统:模板定制与SEO优化一键生成指南  Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】  Linux系统运维自动化项目教程_Ansible批量管理实战  Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】  JavaScript中如何操作剪贴板_ClipboardAPI怎么用  智能起名网站制作软件有哪些,制作logo的软件?  laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法  HTML 中如何正确使用模板变量为元素的 name 属性赋值  php 三元运算符实例详细介绍  Laravel中间件如何使用_Laravel自定义中间件实现权限控制  Android中AutoCompleteTextView自动提示  如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)  PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)  Laravel如何配置任务调度?(Cron Job示例)  Laravel怎么集成Log日志记录_Laravel单文件与每日日志配置及自定义通道【详解】  Laravel如何实现API版本控制_Laravel API版本化路由设计策略  教你用AI将一段旋律扩展成一首完整的曲子