一个索引让性能提升170倍,Explain教你看懂真相
一个索引让性能提升170倍Explain教你看懂真相干了八年的数据库工程自认为对SQL调优已经驾轻就熟。直到上个月一个线上慢查询把我按在地上摩擦了整整两天——一个简单的订单查询跑了5.2秒业务方天天催用户投诉不断。最后排查下来问题出在一个被我忽视的索引上。今天就把这次踩坑经历掰开揉碎讲清楚希望能帮正在做SQL优化的你少走弯路。一、问题复现那个让人头疼的慢查询先说说背景。我们有个电商订单系统订单表 orders 大概有800万条数据每天还在以5万条的速度增长。业务方反馈说查询某个时间范围内某个用户的订单列表页面加载要等五六秒用户体验极差。原始查询语句大概是这样的sqlSELECTo.order_id,o.user_id,o.order_amount,o.order_status,o.created_at,oi.product_name,oi.product_priceFROM orders oLEFT JOIN order_items oi ON o.order_id oi.order_idWHERE o.user_id 123456AND o.created_at 2025-06-01AND o.created_at 2025-07-01ORDER BY o.created_at DESCLIMIT 20;看起来很简单对吧一个用户ID加时间范围再加个关联查询按理说不应该慢到哪去。但现实就是这么打脸——执行计划显示这个查询走了全表扫描扫描了将近400万行数据才返回20条结果。二、问题诊断Explain 不会骗人遇到慢查询第一件事就是看执行计划。用 Explain 分析一下sqlEXPLAIN SELECTo.order_id,o.user_id,o.order_amount,o.order_status,o.created_atFROM orders oWHERE o.user_id 123456AND o.created_at 2025-06-01AND o.created_at 2025-07-01ORDER BY o.created_at DESCLIMIT 20;执行计划结果idselect_typetabletypepossible_keyskeyrowsExtra1SIMPLEoALLidx_user_id,idx_created_atNULL3987654Using where; Using filesort看到 typeALL 和 rows3987654 的时候我整个人都不好了。明明有索引为什么没走再看 possible_keys 一栏MySQL 知道有 idx_user_id 和 idx_created_at 两个单列索引但 keyNULL 表示它一个都没用。这个问题其实很典型当查询条件涉及多个列而每个列只有单独索引时MySQL 的优化器可能认为走索引还不如全表扫描快。尤其是当 user_id123456 这个条件的选择性不够高时——这个用户有20万条订单记录占全表的2.5%MySQL 觉得扫索引再回表还不如直接扫全表。更糟糕的是Extra 列还出现了 Using filesort这意味着排序也没走索引需要在内存或磁盘上做额外的排序操作。双重打击之下5秒的查询时间也就不奇怪了。三、解决方案联合索引的正确打开方式问题清楚了解决方案也就明确了创建一个联合索引让查询条件和排序都能利用索引。sqlALTER TABLE orders ADD INDEX idx_user_created (user_id, created_at DESC);这里有几个关键点需要注意1、字段顺序很重要把等值查询条件 user_id 放在前面范围查询条件 created_at 放在后面。这是联合索引设计的基本原则——等值条件在前范围条件在后。2、排序字段直接定义DESCMySQL 8.0 支持降序索引如果查询中 ORDER BY ... DESC 是常态直接在索引定义时指定 DESC可以避免文件排序。3、覆盖索引的考量如果查询只涉及 user_id、created_at、order_amount、order_status 这几个字段可以做一个覆盖索引把查询字段都包含进去避免回表sqlALTER TABLE orders ADD INDEX idx_user_created_cover(user_id, created_at DESC, order_amount, order_status);创建完索引后再看执行计划idselect_typetabletypepossible_keyskeyrowsExtra1SIMPLEorefidx_user_createdidx_user_created198Using where; Using indextyperef扫描行数从400万降到198Extra 里 Using index 表示索引覆盖不用回表。查询时间从5.2秒降到了0.03秒快了170多倍。四、关联查询的索引优化解决了主查询的问题还得看看 LEFT JOIN 那边的情况。order_items 表有1200万条数据关联条件是 o.order_id oi.order_id如果 oi.order_id 上没有索引关联查询一样会慢。检查一下sqlSHOW INDEX FROM order_items;果然order_items 表的主键是自增的 item_idorder_id 上只有一个普通索引。不过这个索引已经能用了关联查询时 MySQL 会先驱动 orders 表用联合索引快速定位然后通过 order_id 索引去 order_items 表查找。如果 order_items 表经常按 order_id 做关联查询可以考虑把索引改成联合索引把经常查询的字段也包含进去sqlALTER TABLE order_items ADD INDEX idx_order_product(order_id, product_name, product_price);这样关联查询时不仅能用上索引还能直接从索引中获取 product_name 和 product_price完全避免回表。五、优化后的完整查询与效果对比优化后的完整查询sqlSELECTo.order_id,o.user_id,o.order_amount,o.order_status,o.created_at,oi.product_name,oi.product_priceFROM orders oLEFT JOIN order_items oi ON o.order_id oi.order_idWHERE o.user_id 123456AND o.created_at 2025-06-01AND o.created_at 2025-07-01ORDER BY o.created_at DESCLIMIT 20;优化效果对比指标优化前优化后扫描行数3987654198查询类型ALL全表扫描ref索引引用排序方式filesort文件排序索引排序查询耗时5.2秒0.03秒回表次数大量回表索引覆盖六、这次踩坑教会我的几个道理1、单列索引不是万能药。很多开发同学习惯在每个查询字段上单独建索引觉得这样就能覆盖所有查询场景。但实际工作中多条件查询才是常态联合索引往往比单列索引高效得多。2、Explain 是调优的第一工具。遇到慢查询不要凭感觉猜直接用 Explain 看执行计划。重点关注 type、rows、Extra 三列它们能告诉你查询到底慢在哪。3、索引设计要考虑排序。很多人只关注 WHERE 条件忽略了 ORDER BY。如果排序字段能包含在索引中MySQL 可以直接按索引顺序读取数据省掉 filesort 的开销。4、不要过度索引。联合索引虽然好但不是越多越好。每个索引都会增加写入开销占用存储空间。根据实际查询模式设计最核心的几个索引就够了。5、覆盖索引是性能利器。如果查询字段都能从索引中获取MySQL 就不需要回表这能减少大量随机 I/O。尤其是在 OLTP 场景下覆盖索引的效果非常明显。七、几个实用的索引优化建议在日常工作中我总结了几条索引优化的实战经验1、分析慢查询日志。MySQL 的慢查询日志是宝藏定期分析能发现很多隐藏的性能问题。可以用 pt-主题-digest 工具来分析慢查询日志找出最耗时的查询。2、关注索引选择性。索引列的值越分散选择性越高索引效果越好。像性别这种只有两个值的列建索引意义不大。而用户ID、订单号这类高选择性的列索引效果就很明显。3、避免在索引列上做函数操作。比如 WHERE DATE(created_at) 2025-06-01这会让索引失效。应该改成 WHERE created_at 2025-06-01 AND created_at 2025-06-02。4、合理使用索引提示。有时候 MySQL 的优化器会选错索引可以用 FORCE INDEX 或 USE INDEX 来强制指定索引。不过这只是临时方案根本解决还是要优化索引设计。5、定期维护索引。随着数据的增删改索引会产生碎片影响查询性能。定期用 OPTIMIZE TABLE 重建索引可以保持索引的高效性。八、写在最后那次线上事故之后我花了一周时间把系统里所有核心查询都过了一遍用 Explain 逐个分析优化了十几个慢查询。最大的感悟是索引优化不是一锤子买卖而是需要持续关注和迭代的过程。业务在变数据量在涨查询模式也在变。今天好用的索引三个月后可能就成了瓶颈。定期做性能巡检用 Explain 和慢查询日志做体检才能让数据库始终保持最佳状态。希望这次踩坑经历能给你一些启发。如果你在 SQL 优化上也有什么心得或者踩过什么坑欢迎一起交流探讨。注意本文所介绍的软件及功能均基于公开信息整理仅供用户参考。在使用任何软件时请务必遵守相关法律法规及软件使用协议。同时本文不涉及任何商业推广或引流行为仅为用户提供一个了解和使用该工具的渠道。你在生活中时遇到了哪些问题你是如何解决的欢迎在评论区分享你的经验和心得希望这篇文章能够满足您的需求如果您有任何修改意见或需要进一步的帮助请随时告诉我感谢各位支持可以关注我的个人主页找到你所需要的宝贝。博文入口山峰哥-CSDN博客复制到【浏览器】打开即可,宝贝入口常用软件宝贝精品文件作者郑重声明本文内容为本人原创文章纯净无利益纠葛如有不妥之处请及时联系修改或删除。诚邀各位读者秉持理性态度交流共筑和谐讨论氛围

相关新闻

数码管驱动方案全解析:从基础到进阶实战

数码管驱动方案全解析:从基础到进阶实战

1. 数码管驱动基础与四种方案概览 数码管作为电子设计中最基础的显示器件之一,从简单的家电到工业控制面板随处可见。但很多初学者在驱动数码管时总会遇到亮度不均、闪烁、占用IO过多等问题。今天我就结合自己十年硬件设计的踩坑经验,详细剖析四种最实用…

2026/10/15 11:21:48 阅读更多 →
智慧银行反欺诈大数据管控平台建设方案:从规则拦截到图谱智能,重构银行实时风控中枢(PPT)

智慧银行反欺诈大数据管控平台建设方案:从规则拦截到图谱智能,重构银行实时风控中枢(PPT)

在今天的银行业,反欺诈早已不是“多配几条规则、多查几笔交易”那么简单。移动银行、线上开户、远程授信、互联网支付、开放生态、代理渠道、跨平台行为、设备伪装和团伙作案,让欺诈从单点攻击演变成了链式、批量化、隐蔽化和高对抗性的系统工程。银行若…

2026/10/15 2:41:10 阅读更多 →
STM32启动流程详解:从复位到main函数执行

STM32启动流程详解:从复位到main函数执行

1. STM32启动流程全景概览当按下STM32开发板的电源按钮时,芯片内部究竟发生了什么?这个看似简单的过程实际上包含了一系列精密的硬件自动化和软件初始化操作。作为嵌入式开发者,理解从电源接通到main函数执行之间的完整流程,对于调…

2026/10/14 23:11:27 阅读更多 →

最新新闻

Grad-CAM原理解析与工业级实现指南

Grad-CAM原理解析与工业级实现指南

1. 这不是“画个热力图”那么简单:Grad-CAM到底在解决什么问题?Grad-CAM可视化,这五个字最近在模型可解释性讨论里出现频率极高,但很多人一上手就卡在“为什么我的热力图全是噪点”“为什么关键区域没亮起来”“为什么不同层的图完…

2026/10/15 15:22:08 阅读更多 →
Vue3源码解析:从effect看watch与computed的设计与调度

Vue3源码解析:从effect看watch与computed的设计与调度

Vue 3 的watch和computed这两条 API,可能是绝大多数项目里使用率最高的响应式能力,但也是误解最多的一对。平时查资料,大家见到的多半是用法层面的总结:computed 用于同步派生状态、watch 用于执行副作用、能用 computed 就别用 w…

2026/10/15 15:22:08 阅读更多 →
碰碰好评卡功能模块开发实战指南 附全流程实现思路与踩坑汇总

碰碰好评卡功能模块开发实战指南 附全流程实现思路与踩坑汇总

碰碰好评卡功能模块开发实战指南 附全流程实现思路与踩坑汇总 在电商、本地生活、上门服务等各类线上业务场景中,用户评价是影响商品/服务转化的核心指标,碰碰好评卡作为引导用户主动完成评价的核心功能模块,需要兼顾触发灵活性、多端兼容性、…

2026/10/15 15:22:08 阅读更多 →
ZooKeeper核心机制精讲:数据模型、Watch与Leader选举

ZooKeeper核心机制精讲:数据模型、Watch与Leader选举

1. 为什么分布式系统里必须有ZooKeeper这样的角色早些年我做分布式系统的时候,最头疼的事情不是接口怎么写,而是几台机器之间怎么“商量事儿”。比如一个服务一共开了三个实例,数据库连接池一共 60 个连接,分配 30 个给 A、20 个给…

2026/10/15 15:22:08 阅读更多 →
okhttputils 使用指南:基于 OkHttp 3.3.1 的 Android 网络请求封装库完整实战

okhttputils 使用指南:基于 OkHttp 3.3.1 的 Android 网络请求封装库完整实战

网络移动开发 【免费下载链接】okhttputils [停止维护]okhttp的辅助类 项目地址: https://gitcode.com/gh_mirrors/ok/okhttputils 点击查看 免费下载 本文是一份围绕开源仓库 okhttputils 的完整使用指南。okhttputils 是一套对 Square OkHttp 的辅助封装类&#…

2026/10/15 15:22:08 阅读更多 →
基于单片机的电阻炉温控系统:DS18B20与PID调参实战

基于单片机的电阻炉温控系统:DS18B20与PID调参实战

简介:基于单片机的电阻炉温控制系统设计,是一套面向电子、自动化专业学生及嵌入式初学者的完整课程设计/毕设方案,涵盖DS18B20数字测温、单片机温度曲线动态跟踪和上位机通信三大环节。方案从硬件原理图、下位机控制程序到VB上位机界面均有实…

2026/10/15 15:21:06 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →