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

SQL语句优化的步骤详解

文章目录

  • 前言
  • 第一步:问题发现与定位
    • 1.1 开启慢查询日志
    • 1.2 收集问题SQL
  • 第二步:执行计划分析
    • 2.1 使用EXPLAIN分析
    • 2.2 重点关注的字段
    • 2.3 执行计划示例分析
  • 第三步:索引设计与优化
    • 3.1 创建合适的索引
    • 3.2 复合索引的设计原则
    • 3.3 索引覆盖优化
  • 第四步:SQL语句结构优化
    • 4.1 JOIN优化
    • 4.2 分页查询优化
    • 4.3 条件优化
  • 第五步:验证优化效果
  • 总结

前言

在实际项目中,随着数据量的增长和业务复杂度的提升,SQL性能问题逐渐凸显。很多开发者面对慢查询时往往不知从何下手,要么盲目加索引,要么随意修改SQL结构。实际上,SQL优化是一个系统性的工程,需要遵循科学的方法论。

第一步:问题发现与定位

1.1 开启慢查询日志

首先需要开启MySQL的慢查询日志来捕获性能问题:

-- 查看慢查询日志配置
SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';-- 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2; -- 设置2秒为慢查询阈值

1.2 收集问题SQL

从慢查询日志中提取问题SQL,重点关注:

  • 执行时间超长的查询
  • 执行频率高的查询
  • 扫描行数过多的查询

第二步:执行计划分析

2.1 使用EXPLAIN分析

EXPLAIN是SQL优化的核心工具,能够展示MySQL执行SQL的详细计划:

EXPLAIN SELECT * FROM users u 
JOIN orders o ON u.id = o.user_id 
WHERE u.status = 1 AND o.create_time > '2024-01-01';

2.2 重点关注的字段

type字段(连接类型)

  • ALL: 全表扫描,性能最差
  • index: 索引全扫描
  • range: 索引范围扫描
  • ref: 索引等值查询
  • const: 常量查询,性能最佳

key字段

  • 显示实际使用的索引
  • 如果为NULL,说明没有使用索引

rows字段

  • 预估的扫描行数
  • 数值越小越好

Extra字段

  • Using filesort: 需要额外排序,性能较差
  • Using temporary: 使用临时表
  • Using index: 索引覆盖,性能较好

2.3 执行计划示例分析

-- 优化前
mysql> EXPLAIN SELECT * FROM orders WHERE status = 1 ORDER BY create_time DESC LIMIT 10;
+----+-------------+--------+------+---------------+------+---------+------+-------+-----------------------------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows  | Extra                       |
+----+-------------+--------+------+---------------+------+---------+------+-------+-----------------------------+
|  1 | SIMPLE      | orders | ALL  | NULL          | NULL | NULL    | NULL | 50000 | Using where; Using filesort |
+----+-------------+--------+------+---------------+------+---------+------+-------+-----------------------------+-- 分析:全表扫描50000行,还需要额外排序,性能很差

第三步:索引设计与优化

3.1 创建合适的索引

根据执行计划分析结果,设计合理的索引:

-- 针对WHERE条件创建索引
CREATE INDEX idx_orders_status ON orders(status);-- 针对ORDER BY创建复合索引
CREATE INDEX idx_orders_status_time ON orders(status, create_time);

3.2 复合索引的设计原则

遵循"最左前缀匹配"原则:

-- 创建复合索引
CREATE INDEX idx_user_age_city ON users(age, city, name);-- 以下查询可以使用索引
SELECT * FROM users WHERE age = 25;
SELECT * FROM users WHERE age = 25 AND city = 'Beijing';
SELECT * FROM users WHERE age = 25 AND city = 'Beijing' AND name = 'Zhang';-- 以下查询无法使用索引
SELECT * FROM users WHERE city = 'Beijing'; -- 跳过了最左边的age

3.3 索引覆盖优化

尽量让查询字段都包含在索引中,避免回表操作:

-- 原始查询
SELECT id, name, email FROM users WHERE age = 25;-- 创建覆盖索引
CREATE INDEX idx_users_age_id_name_email ON users(age, id, name, email);

第四步:SQL语句结构优化

4.1 JOIN优化

选择合适的JOIN类型:

-- 优化前:使用子查询
SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE status = 1
);-- 优化后:使用INNER JOIN
SELECT DISTINCT u.* FROM users u 
INNER JOIN orders o ON u.id = o.user_id 
WHERE o.status = 1;

优化JOIN顺序:

-- 让小表驱动大表
SELECT * FROM small_table s
JOIN big_table b ON s.id = b.small_id
WHERE s.status = 1;

4.2 分页查询优化

传统分页的问题:

-- 深分页性能差
SELECT * FROM users ORDER BY id LIMIT 100000, 20;

优化方案:

-- 方案1:使用子查询优化
SELECT * FROM users WHERE id >= (SELECT id FROM users ORDER BY id LIMIT 100000, 1
) ORDER BY id LIMIT 20;-- 方案2:使用游标分页
SELECT * FROM users WHERE id > 100000 ORDER BY id LIMIT 20;

4.3 条件优化

避免在WHERE子句中使用函数:

-- 优化前
SELECT * FROM orders WHERE YEAR(create_time) = 2024;-- 优化后
SELECT * FROM orders WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01';

合理使用OR条件:

-- 优化前
SELECT * FROM users WHERE name = 'Zhang' OR email = 'zhang@example.com';-- 优化后:使用UNION
SELECT * FROM users WHERE name = 'Zhang'
UNION
SELECT * FROM users WHERE email = 'zhang@example.com';

第五步:验证优化效果

-- 优化后再次执行EXPLAIN
EXPLAIN SELECT * FROM orders WHERE status = 1 ORDER BY create_time DESC LIMIT 10;
+----+-------------+--------+-------+-------------------------+------------------------+---------+------+------+-------+
| id | select_type | table  | type  | possible_keys           | key                    | key_len | ref  | rows | Extra |
+----+-------------+--------+-------+-------------------------+------------------------+---------+------+------+-------+
|  1 | SIMPLE      | orders | ref   | idx_orders_status_time  | idx_orders_status_time | 4       | const|   20 | NULL  |
+----+-------------+--------+-------+-------------------------+------------------------+---------+------+------+-------+-- 优化效果:从全表扫描50000行变为索引扫描20行

总结

SQL优化是一个系统性的工程,需要遵循科学的方法论:

  1. 问题发现:通过监控和日志及时发现性能问题
  2. 深入分析:使用EXPLAIN等工具分析执行计划
  3. 索引设计:基于查询模式设计合理的索引结构
  4. 语句优化:重构SQL语句,改善执行逻辑
  5. 效果验证:对比优化前后的性能指标
  6. 持续改进:建立长期监控和优化机制

文章转载自:

http://txpeuJyz.wjzzh.cn
http://Zjh6USNL.wjzzh.cn
http://Ddm59DFP.wjzzh.cn
http://z4RppXhb.wjzzh.cn
http://2mOgnLFV.wjzzh.cn
http://c4naBPYp.wjzzh.cn
http://AJS2qYwn.wjzzh.cn
http://wo35tEZn.wjzzh.cn
http://2XzityRE.wjzzh.cn
http://cytw0e26.wjzzh.cn
http://BbeB2Lx7.wjzzh.cn
http://RW9B0G3Y.wjzzh.cn
http://KVDmhOVQ.wjzzh.cn
http://Fd0aUxZ4.wjzzh.cn
http://h9jGP7nC.wjzzh.cn
http://ZX8qT0eX.wjzzh.cn
http://6MdsjWLI.wjzzh.cn
http://ZKk9uI3r.wjzzh.cn
http://ztHeY8xC.wjzzh.cn
http://5WChu4hy.wjzzh.cn
http://cswDNtSa.wjzzh.cn
http://jkLhKx54.wjzzh.cn
http://lNDsGhXL.wjzzh.cn
http://flyl3rdo.wjzzh.cn
http://qqTDThfB.wjzzh.cn
http://vQGKlPN3.wjzzh.cn
http://6OgZTel8.wjzzh.cn
http://DSIRkfUa.wjzzh.cn
http://VFmYLYPR.wjzzh.cn
http://X1MXVXxb.wjzzh.cn
http://www.dtcms.com/a/381707.html

相关文章:

  • VSCode 的百度 AI编程插件
  • 【OpenAPI】OpenAPI 3.0x 格式解析技术指南
  • leetcode 14 最长的公共前缀
  • B. Bobritto Bandito
  • 体会bootstrap
  • ConcurrentHashMap 的底层原理及是如何实现线程安全的?
  • linux中查找包含xxx内容的文件
  • 【Linux】添加sudo权限/设置默认权限/配置别名/配置新用户的密码策略
  • 32.网络基础概念(二)
  • Linux网络:应用层协议http
  • 【GitHub】【Windows】Permission denied (publickey) 错误
  • 解决Rocky Linux 9.6下Beyond Compare私钥连接失败问题
  • ubuntu git push每次都要输入密码怎么解决只输入一次密码
  • OpenCV 教程——从像素到智能:图像预处理关键技巧与零售货架缺货检测实战
  • 面试鸭Java八股之Kafka
  • 【学习K230-例程23】GT6700-音频FFT柱状图
  • 【Chrome】chrome 调试工具的network选项卡,如何同时过滤出doc js css
  • python--MediaPipe-opencv眨眼检测
  • 2.2.蓝桥杯-数位递增的数
  • leetcode 3541. 找到频率最高的元音和辅音 简单
  • Spring Boot 与微服务网关集成问题:Zuul、Spring Cloud Gateway 与鉴权策略
  • algorithm | Big O notation
  • 开发指南:使用 MQTTNet 库构建 .Net 物联网 MQTT 应用程序
  • 【代码随想录day 25】 力扣 47.全排列 II
  • 驱动开发系列73 - clEnqueueNDRangeKernel实现
  • Unity 性能优化 之 静态资源优化 (音频 | 模型 | 纹理 | 动画)
  • 服装贸易管理系统推荐及软件选型指南
  • 音视频的下一站:协议编排、低时延工程与国标移动化接入的系统实践
  • Python核心技术开发指南(064)——with语句
  • 打造高效AI助手的秘密武器 - Parlant