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

MySQL慢查询优化实战:从日志分析到SQL重构全流程

⚡ MySQL慢查询优化实战:从日志分析到SQL重构全流程

一篇带你从发现慢查询 → 分析 → 优化 → 测试的完整实战教程
🧩 关键词:MySQL优化 / 性能分析 / 慢查询 / 索引设计


🔍 一、前言

在大型业务系统中,MySQL 慢查询会导致:

  • 系统响应变慢
  • 页面加载延迟
  • 高并发下锁等待严重
    在这里插入图片描述

解决方案就是 找到慢查询 → 分析执行计划 → 优化 SQL → 设计合理索引
本文通过一个 电商订单查询系统 的实例,带你全流程实战演示。


🏗 二、业务场景

假设我们有一个电商系统 orders 表:

CREATE TABLE orders (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT NOT NULL,product_id BIGINT NOT NULL,status VARCHAR(20),total_amount DECIMAL(10,2),created_at DATETIME,INDEX idx_user_created (user_id, created_at)
);

在这里插入图片描述

业务需求:

  • 查询某用户在某时间段的订单
  • 查询某状态订单总额
  • 高峰期每天有百万级订单

🧾 三、开启慢查询日志

修改 MySQL 配置文件 my.cnf

[mysqld]
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1  # 秒
log_queries_not_using_indexes = 1

重启 MySQL:

sudo systemctl restart mysql

查询慢查询日志示例:

# Time: 2025-11-05T15:00:01.000000Z
# User@Host: root[root] @ localhost []
# Query_time: 3.542 Lock_time: 0.000 Rows_sent: 500 Rows_examined: 100000
SELECT * FROM orders WHERE user_id=12345 AND created_at BETWEEN '2025-11-01' AND '2025-11-05';

注意:Rows_examined=100,000 → 查询扫描了大量行,效率低


🧐 四、执行计划分析

使用 EXPLAIN 分析 SQL:

EXPLAIN SELECT * FROM orders
WHERE user_id=12345 AND created_at BETWEEN '2025-11-01' AND '2025-11-05';

输出示例:

idselect_typetabletypepossible_keyskeyrowsExtra
1SIMPLEordersrefidx_user_createdidx_user_created100000Using where

分析:

  • 查询使用了 idx_user_created 索引,但扫描行数仍然多
  • 原因:索引顺序和条件不完全匹配

🛠 五、SQL重构与索引优化

1️⃣ 优化 SQL

原 SQL:

SELECT * FROM orders 
WHERE user_id=12345 AND created_at BETWEEN '2025-11-01' AND '2025-11-05';

优化 SQL:

SELECT id, product_id, total_amount 
FROM orders
WHERE user_id=12345 AND created_at >= '2025-11-01' AND created_at <= '2025-11-05';

✅ 优化点:

  • 只查询必要字段,避免 SELECT *
  • 避免不必要的数据扫描

2️⃣ 调整索引

当前索引:

INDEX idx_user_created (user_id, created_at)

优化方案:

  • 如果查询经常按 status 和时间筛选,可加复合索引:
ALTER TABLE orders 
ADD INDEX idx_user_status_created (user_id, status, created_at);
  • 这样查询 WHERE user_id=12345 AND status='PAID' AND created_at BETWEEN ... 可以直接走索引覆盖

3️⃣ 验证优化效果

执行优化后的 SQL:

EXPLAIN SELECT id, product_id, total_amount 
FROM orders
WHERE user_id=12345 AND status='PAID' AND created_at BETWEEN '2025-11-01' AND '2025-11-05';

输出示例:

idselect_typetabletypepossible_keyskeyrowsExtra
1SIMPLEordersrefidx_user_status_createdidx_user_status_created500Using index

✅ Rows 从 100,000 降到 500,查询速度提升近 200 倍


🔁 六、慢查询优化全流程总结

  1. 发现慢查询

    • 慢查询日志 + long_query_time
    • pt-query-digest 分析大量慢查询
  2. 分析执行计划

    • EXPLAIN 查看扫描方式、索引使用情况
    • 关注 rowsExtra
  3. SQL优化

    • 避免 SELECT *
    • 使用必要字段
    • 合理拆分复杂查询
  4. 索引优化

    • 复合索引覆盖查询条件
    • 使用前缀索引或联合索引减少扫描量
    • 删除冗余索引
  5. 验证与回归测试

    • EXPLAIN + 实测响应时间
    • 高并发下压测

📊 七、日志分析工具推荐

  • mysqldumpslow
  • Percona Toolkit: pt-query-digest
  • Grafana + Prometheus + MySQL Exporter
  • 慢查询日志可视化面板,辅助优化


!实战范例: MySQL慢查询优化实战项目演示:百万订单表优化


1️⃣ 数据准备:生成百万级订单表

CREATE DATABASE IF NOT EXISTS shop;
USE shop;DROP TABLE IF EXISTS orders;
CREATE TABLE orders (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT NOT NULL,product_id BIGINT NOT NULL,status VARCHAR(20),total_amount DECIMAL(10,2),created_at DATETIME,INDEX idx_user_created (user_id, created_at)
);-- 插入测试数据(模拟100万条)
DELIMITER $$CREATE PROCEDURE populate_orders()
BEGINDECLARE i INT DEFAULT 1;WHILE i <= 1000000 DOINSERT INTO orders(user_id, product_id, status, total_amount, created_at)VALUES(FLOOR(1 + RAND() * 10000),    -- user_idFLOOR(1 + RAND() * 500),      -- product_idELT(FLOOR(1 + RAND()*3), 'PAID','PENDING','CANCELLED'),ROUND(RAND()*1000, 2),NOW() - INTERVAL FLOOR(RAND()*30) DAY);SET i = i + 1;END WHILE;
END$$DELIMITER ;CALL populate_orders();

✅ 这样我们就有了百万级订单表,可真实模拟慢查询。


2️⃣ 原始慢查询测试

原 SQL 示例(经常使用场景):

SELECT * 
FROM orders 
WHERE user_id=1234 AND created_at BETWEEN '2025-11-01' AND '2025-11-05';

执行前加 EXPLAIN 分析:

EXPLAIN SELECT * 
FROM orders 
WHERE user_id=1234 AND created_at BETWEEN '2025-11-01' AND '2025-11-05';

输出示例:

idtabletypepossible_keyskeyrowsExtra
1ordersrefidx_user_createdidx_user_created100000Using where

Rows=100,000 → 仍然扫描大量行,效率低


3️⃣ SQL重构与索引优化

优化 SQL

  • 只查询需要字段
  • 避免 SELECT *
SELECT id, product_id, total_amount 
FROM orders 
WHERE user_id=1234 AND created_at BETWEEN '2025-11-01' AND '2025-11-05';

新增复合索引

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

4️⃣ 优化后性能验证

EXPLAIN SELECT id, product_id, total_amount 
FROM orders 
WHERE user_id=1234 AND status='PAID'AND created_at BETWEEN '2025-11-01' AND '2025-11-05';
idtabletypekeyrowsExtra
1ordersrefidx_user_created_status500Using index

✅ Rows 从 100,000 → 500,查询速度提升近 200倍


5️⃣ Node.js 测试脚本(可选)

用 Node.js 模拟实际请求,测试查询性能:

const mysql = require('mysql2/promise');(async function() {const conn = await mysql.createConnection({host: 'localhost',user: 'root',password: '123456',database: 'shop'});console.time('原SQL');await conn.query(`SELECT * FROM orders WHERE user_id=1234 AND created_at BETWEEN '2025-11-01' AND '2025-11-05'`);console.timeEnd('原SQL');console.time('优化SQL');await conn.query(`SELECT id, product_id, total_amount FROM orders WHERE user_id=1234 AND status='PAID' AND created_at BETWEEN '2025-11-01' AND '2025-11-05'`);console.timeEnd('优化SQL');await conn.end();
})();

运行结果示例:

原SQL: 2450ms
优化SQL: 12ms

6️⃣ 总结

通过这个实战项目,我们完成了:

  1. 百万级订单表数据生成
  2. 原始 SQL 慢查询分析
  3. SQL 重构 + 索引优化
  4. 查询性能测试验证

✅ 实战结果:

  • 原 SQL:Rows 扫描 10万+,耗时 2-3秒
  • 优化 SQL:Rows 扫描 500,耗时 10-15ms
  • 高并发场景下性能显著提升

http://www.dtcms.com/a/572745.html

相关文章:

  • 每日一练 1(双指针)(单调性)
  • 从云平台到系统内核:SmartMediakit如何重构实时视频系统
  • XC6SLX45T-3FGG484I Xilinx Spartan-6 FPGA
  • 函数栈帧的创建与销毁详解(C语言拓展版)
  • 从 Grok 4 多智能体协同到 RAG 范式革命:2025 年 AI 工作流的技术重构生成
  • Macos系统上搭建Hadoop详细过程
  • 景德镇市城市建设规划网站安徽建设信息网
  • 11.5 LeetCode 题目汇总与解题思路
  • 三维空间变换:矩阵正交规范化的作用
  • E-House市场迎来爆发期?2025年全球规模与投资前景深度分析
  • 【尚庭公寓152-157】[第6天]【配置阿里云号码认证服务】
  • 使用DrissionPage实现携程酒店信息智能爬取
  • 数据结构之**二叉树**超全秘籍宝典2
  • win32k!ProcessKeyboardInput函数分析---登录界面ctrl+alt+del键的处理
  • 网站版权信息修改wordpress釆集插件破解
  • Springcloud_day01
  • 理解提示词Prompt
  • iOS 抓不到包怎么办?工程化排查与替代抓包方案(抓包/HTTPS/Charles代理/tcpdump)
  • 告别密码和防火墙——将 Git 仓库从 HTTPS 切换到 SSH 连接
  • Fiddler抓包工具详解,HTTP/HTTPS抓包、代理设置与调试技巧一站式教程(含实战案例)
  • Go语言爬虫:采集百度热榜并将拼装后的json写入txt文件
  • 图模式分析:PyTorch Compile组件解析
  • Microsoft Fabric - 试一下在前端应用中使用 GraphQL API去连接Lakehouse
  • 测试套件缩减方法
  • Oracle SQL Developer设置打开表的时候如何是新窗口中打开
  • 新开传奇网站刚开一秒甘南网站设计公司
  • postman 安装教程
  • 网站建站流程图简单工程承包合同
  • 【Linux系统编程】进程概念(三)进程状态
  • 360极速浏览器 安装猫抓插件的方法