当前位置: 首页 > news >正文

蓝易云 :MySQL之优化SELECT语句

蓝易云:MySQL 之优化 SELECT 语句(把“慢”拆成可控的成本)⚡️

优化 SELECT 的本质是做三件事:让优化器选到更好的执行计划、让存储引擎少读数据页、让返回路径少做无效工作。你可以把一次查询的成本粗略理解为:
[
\text{总成本} \approx \text{扫描行数} \times \text{每行代价} + \text{排序/分组代价} + \text{回表代价}
]
目标就是把扫描行数回表次数排序/临时表这三块压下去。🙂


1)先定位:用 EXPLAIN 把“猜测”变“证据”🔍

EXPLAIN SELECT id, user_id, amount FROM orders WHERE user_id = 10086 AND status = 1 ORDER BY created_at DESC LIMIT 20;

解释(逐行抓重点)

  • EXPLAIN:不跑结果,只输出执行计划,用来判断有没有走到你期望的索引。

  • SELECT id, user_id, amount:只取必要字段,减少 IO 与网络传输;避免SELECT *导致多余列读取。

  • WHERE user_id = ... AND status = ...:等值过滤是索引最喜欢的形态。

  • ORDER BY created_at DESC LIMIT 20:如果能用同一个索引顺序返回,就能避免额外排序;否则容易出现“额外排序/临时表”的信号。


2)索引:让查询“走对路”,并尽量做到 覆盖索引 ✅

ALTER TABLE orders ADD INDEX idx_user_status_ct (user_id, status, created_at, id);

解释

  • ALTER TABLE ... ADD INDEX:创建索引是优化 SELECT 的最高杠杆之一。

  • idx_user_status_ct (user_id, status, created_at, id)

    • user_id, status放前面:对应WHERE的高频过滤列,让扫描范围迅速收窄。

    • created_at接着:配合ORDER BY created_at,有机会直接“按索引顺序”取前 20 条,减少排序。

    • id放末尾:常用于让索引更容易覆盖查询或减少回表(是否需要取决于查询返回列)。

  • 核心目标:让查询尽量变成Index Range Scan + 少回表,甚至直接覆盖索引(返回字段都在索引里)。


3)WHERE 写法:别让索引“失明”👀

-- 反例:对列做函数运算,容易导致索引失效 SELECT * FROM orders WHERE DATE(created_at) = '2026-03-04'; -- 正例:改成范围查询 SELECT * FROM orders WHERE created_at >= '2026-03-04 00:00:00' AND created_at < '2026-03-05 00:00:00';

解释

  • 反例DATE(created_at):把列先计算再比较,索引通常无法按原值做范围定位,扫描量会膨胀。

  • 正例用时间范围:让created_at能参与索引范围扫描,扫描行数显著下降。

  • 同类坑还有:隐式类型转换(字符串比数字)、前导通配符LIKE '%abc'OR混合多列导致难以用单一索引。


4)分页:用“定位翻页”替代 OFFSET 大跳跃 🚀

-- 慢:OFFSET 越大越慢(MySQL 需要跳过前 N 行) SELECT id, created_at FROM orders WHERE user_id = 10086 ORDER BY created_at DESC LIMIT 20 OFFSET 200000; -- 快:基于“上一页最后一条”的定位翻页(Seek Method) SELECT id, created_at FROM orders WHERE user_id = 10086 AND created_at < '2026-03-04 12:00:00' ORDER BY created_at DESC LIMIT 20;

解释

  • OFFSET 200000:本质是“读出来再丢掉”,越翻越慢。

  • 定位翻页:把上一页末尾的created_at(或(created_at,id))当游标,直接从索引位置继续扫,成本稳定。

  • 若存在相同时间戳,建议用created_at+id作为复合游标,避免漏/重复。


5)高频慢点与对策:一张表对齐思路📌

症状典型原因直接打法
扫描行数巨大索引缺失 / 条件不可用索引补联合索引;把函数/隐式转换改成范围或等值
排序很慢ORDER BY无法用索引顺序把排序列纳入联合索引并匹配顺序;减少排序字段
回表太多只用到二级索引但要取很多列做 覆盖索引;只取必要列
JOIN 慢驱动表不对/条件不走索引小表驱动大表;ON/WHERE列补索引;只 JOIN 必要字段
分组慢临时表/文件排序用索引前缀分组;减少 group by 列;先过滤再聚合

6)优化落地工作流(团队协作更顺)🧠

flowchart TD A[抓慢SQL样本] --> B[EXPLAIN验证计划] B --> C{扫描行数高?} C -->|是| D[补索引/改WHERE写法] C -->|否| E{排序/临时表高?} E -->|是| F[调整ORDER BY/GROUP BY与索引顺序] E -->|否| G{回表多?} G -->|是| H[覆盖索引/减少返回列] G -->|否| I[验证收益与回归测试] I --> J[上线监控与复盘]

最后一句务实建议 ✅

优先级永远是:先少扫 → 再少排 → 最后少回表。把这条链路跑顺,90% 的 SELECT 慢问题都会从“玄学”变成“工程问题”。😄

http://www.jsqmd.com/news/437832/

相关文章:

  • pcb拼板评测排行 哪家拼板方案最靠谱
  • PCB阶梯厚铜工艺 大电流与精细线路兼顾方案
  • NineData 智能数据管理平台新功能发布|2026 年 1-2 月
  • 2026年靠谱的小型挖掘机厂家推荐:液压挖掘机实力厂家推荐 - 品牌宣传支持者
  • 2026年口碑好的洛阳装修旧房改造公司推荐:洛阳装修旧房改造公司精选 - 品牌宣传支持者
  • CISP-PTE认证全攻略:网络安全渗透测试工程师的黄金通行证
  • 零基础入门渗透测试:白帽黑客成长路径与高薪秘籍
  • Django第一次作业
  • 网络安全领域刚需岗位:渗透测试工程师职业真相与前景
  • 启动springboot项目时报错Web server failed to start. Port 8080 was already in use
  • 收藏!网络安全黄金赛道:渗透测试工程师月薪2.2万+,CISP-PTE认证助你快速入行
  • AI与RPA融合:企业数字化提效的实用路径
  • 网络安全攻防之路:渗透测试技能全面指南
  • RPA+AI融合:打破自动化瓶颈,赋能企业智能化转型
  • RPA+AI技术赋能企业智能化运营,助力降本增效与新质生产力发展
  • RPA与AI融合应用:企业智能自动化升级新路径
  • 金属过滤网编织机哪家好?2026铜网编织机源头厂家+铜网编织机源头工厂专业选型指南 - 栗子测评
  • 2026不锈钢网编织机厂家推荐:精密金属网编织机哪家好实力工厂精选 - 栗子测评
  • 2026年评价高的小型挖掘机品牌推荐:微型挖掘机品牌厂家推荐 - 品牌宣传支持者
  • 基于Java+SSM+Flask图书管理系统(源码+LW+调试文档+讲解等)/图书馆管理系统/图书借阅系统/图书管理软件/图书信息管理系统/图书查询系统/图书进销存系统/图书编目系统/图书收藏软件
  • 2026年比较好的气缸SMC代理商厂家推荐:昆山SMC代理商实力品牌厂家推荐 - 品牌宣传支持者
  • 在 MySQL 中使用 `REPLACE` 函数
  • 数字孪生助力复杂地形下大型公路建设与生态保护难题
  • 2026年临颍县旧房改造服务商综合评测与联系指南 - 2026年企业推荐榜
  • 2026全自动金属网编织机厂家+金属丝网编织机厂家推荐:高速金属网编织机厂家,智能高效优选 - 栗子测评
  • 2026年质量好的正式SICK代理商工厂推荐:一级SICK代理商厂家口碑推荐 - 品牌宣传支持者
  • Python 高级实战数据到 AI,量化交易与智能应用
  • 2026年口碑好的SICK代理商品牌推荐:SICK代理商销售厂家推荐 - 品牌宣传支持者
  • IoT-Fast平台:重塑物联网开发新范式,开启全栈智能化时代
  • Bun:JavaScript与TypeScript应用的革命性全栈工具包