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

解决慢SQL问题

解决慢 MySQL 查询的核心思路是 “定位瓶颈 → 针对性优化”,需从“索引、SQL 语句、表结构、配置、硬件”5 个维度逐层排查,以下是可落地的实操步骤:

一、第一步:定位慢查询(找到“谁慢”)

先通过工具锁定慢查询 SQL,避免盲目优化:

  1. 开启 MySQL 慢查询日志

◦ 临时开启(重启失效):
SET GLOBAL slow_query_log = ON; – 开启慢查询日志
SET GLOBAL long_query_time = 1; – 记录执行时间 ≥1 秒的 SQL(根据业务调整阈值)
SET GLOBAL slow_query_log_file = ‘/var/lib/mysql/slow.log’; – 日志存储路径
◦ 永久开启:修改 my.cnf(Linux)或 my.ini(Windows),添加配置后重启 MySQL:
slow_query_log = ON
long_query_time = 1
slow_query_log_file = /var/lib/mysql/slow.log
2. 用工具分析慢查询日志

◦ 用 MySQL 自带的 mysqldumpslow 快速统计:
mysqldumpslow -s c -t 10 /var/lib/mysql/slow.log – 按执行次数(c)排序,取前10条慢SQL
mysqldumpslow -s t -t 10 /var/lib/mysql/slow.log – 按执行时间(t)排序,取前10条
◦ 用可视化工具(如 Percona Toolkit 的 pt-query-digest):更详细分析 SQL 执行频率、锁等待等。

  1. 用 EXPLAIN 分析 SQL 执行计划
    对定位到的慢 SQL,加 EXPLAIN 查看执行计划,判断瓶颈(核心看 type、key、rows 字段):
    EXPLAIN SELECT * FROM order WHERE user_id = 123 AND create_time > ‘2024-01-01’;
    ◦ 关键字段解读:

◦ type:索引使用类型(ALL 表示全表扫描,需优化;range/ref/eq_ref 为优);

◦ key:实际使用的索引(NULL 表示未用索引);

◦ rows:预估扫描的行数(数值越大,效率越低)。

二、第二步:针对性优化(解决“为什么慢”)

根据 EXPLAIN 结果,按“优先级从高到低”优化:

  1. 索引优化(最常见、性价比最高)

慢查询 80% 是“索引问题”,核心是“让 SQL 用上合适的索引”:

• 场景 1:未用索引(key 为 NULL)

◦ 原因:WHERE/JOIN/ORDER BY 字段无索引,或索引失效(如函数操作索引列、模糊查询 %xxx);

◦ 优化:

◦ 为 WHERE 高频过滤字段、JOIN 关联字段、ORDER BY 排序字段建索引(优先联合索引);

◦ 避免索引失效:如 WHERE DATE(create_time) = ‘2024-01-01’ → 改为 WHERE create_time BETWEEN ‘2024-01-01 00:00:00’ AND ‘2024-01-01 23:59:59’(函数操作索引列会失效)。

• 场景 2:用了索引但效率低(type 为 range/index,rows 大)

◦ 原因:索引区分度低(如 gender 字段)、联合索引未遵循“最左匹配”;

◦ 优化:

◦ 删除区分度低的索引(如 gender),改用联合索引;

◦ 调整联合索引字段顺序(过滤性高的字段放左侧,如 idx_user_create (user_id, create_time) 优于 idx_create_user (create_time, user_id))。

• 场景 3:需回表(Extra 有 Using filesort/Using temporary)

◦ 原因:查询字段未被索引覆盖,需回表查聚簇索引;

◦ 优化:用“覆盖索引”(查询字段包含在索引中),如 SELECT user_id, create_time FROM order 可建联合索引 idx_user_create (user_id, create_time),避免回表。

  1. SQL 语句优化(避免“低效写法”)

即使有索引,不合理的 SQL 也会变慢:

• 避免全表扫描:禁用 SELECT *,只查需要的字段(减少数据传输+支持覆盖索引);

• 优化 JOIN 操作:

◦ 小表驱动大表(LEFT JOIN 时,左表为小表);

◦ JOIN 字段必须建索引(避免笛卡尔积);

• 优化排序/分组:

◦ 让排序字段包含在索引中(避免 Using filesort),如 ORDER BY create_time 可结合 WHERE user_id = 123 建联合索引 idx_user_create (user_id, create_time);

◦ 禁用 GROUP BY 非索引字段(避免 Using temporary);

• 优化子查询:子查询改 JOIN(子查询可能重复执行,JOIN 更高效),如:
– 低效子查询
SELECT * FROM order WHERE user_id IN (SELECT id FROM user WHERE age > 30);
– 优化为 JOIN
SELECT o.* FROM order o JOIN user u ON o.user_id = u.id WHERE u.age > 30;
3. 表结构优化(解决“数据量大/结构不合理”)

• 分表分库:单表数据量 > 1000 万行时,拆分表减轻压力:

◦ 水平分表(按行拆分,如订单表按 create_time 分月分表 order_202401、order_202402);

◦ 垂直分表(按列拆分,如用户表拆为 user_base(基础信息)和 user_ext(扩展信息),减少宽表扫描);

• 优化字段类型:

◦ 用更小的字段类型(如 INT 替代 BIGINT,VARCHAR(20) 替代 VARCHAR(255));

◦ 禁用 TEXT/BLOB 存高频查询字段(可拆到单独表,或用前缀索引);

• 删除冗余字段:避免表中存在“可通过其他字段计算得出”的冗余数据(如 order_total 可由 order_detail 表汇总,无需存冗余)。

  1. 配置优化(提升 MySQL 本身性能)

根据服务器硬件调整 my.cnf 配置(需重启 MySQL):

• 缓存优化:

◦ innodb_buffer_pool_size:InnoDB 缓存池大小(建议设为物理内存的 50%~70%,如 16G 内存设为 10G,减少磁盘 IO);

◦ query_cache_size:查询缓存(MySQL 8.0 已移除,5.7 及以下若开启,需确保 query_cache_type=1,但不适用于高频更新表);

• 连接优化:

◦ max_connections:最大连接数(根据业务并发调整,如设为 1000,避免连接耗尽);

◦ wait_timeout:连接超时时间(设为 600 秒,释放闲置连接);

• IO 优化:

◦ innodb_flush_log_at_trx_commit:事务日志刷盘策略(非金融场景设为 2,平衡性能和安全性,避免每次提交都刷盘);

◦ innodb_log_file_size:事务日志文件大小(设为 2G,减少日志切换频率)。

  1. 硬件/架构优化(终极解决方案)

• 硬件升级:当软件优化到极限时,升级 CPU(多核心提升并发处理)、内存(增大缓存池)、SSD(提升磁盘 IO 速度,替代机械硬盘);

• 读写分离:用主从复制(Master 写,Slave 读),将查询压力分摊到从库(如订单查询走从库,下单走主库);

• 缓存引入:用 Redis 缓存高频查询数据(如商品详情、用户信息),避免每次都查 MySQL(如缓存 user_id=123 的用户信息,有效期 10 分钟)。

三、第三步:验证优化效果

优化后,需验证是否生效:

  1. 重新执行 EXPLAIN,确认 type 提升(如 ALL→ref)、rows 减少、key 用上目标索引;

  2. 执行 SHOW PROFILE 查看 SQL 执行耗时(如 Send data 时间减少);

  3. 观察慢查询日志,确认优化后的 SQL 不再被记录;

  4. 监控业务指标(如接口响应时间、MySQL 吞吐量),确认整体性能提升。

总结:优化优先级

  1. 优先索引优化(最快见效,成本最低);

  2. 其次 SQL 语句优化(调整写法,无侵入);

  3. 再到表结构/配置优化(需修改结构或配置,有一定成本);

  4. 最后硬件/架构优化(成本最高,适合大规模业务)。

核心原则:用最小的改动,解决最大的性能问题,避免“过度优化”。

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

相关文章:

  • OpenEuler安装mysql二进制版本
  • 【ADB】常用按键代码:adb的所有模拟按键
  • 网站制作基础教程外贸公司开办流程
  • 山亭建设局网站翻译网页
  • 坂田做网站的公司听小说的网站哪个好
  • CNN-Transformer:PyTorch遥感【含无人机】影像的分类、检测、语义分割和点云分类
  • RAG知识库构建
  • MinMaxScaler Scikit-learn sparkml 稀疏向量
  • 基于WPF实现打印机连接与打印功能
  • 储能材料:弹性势能储能及材料技术突破
  • RapidJSON 自定义内存分配器详解与实战
  • 深度学习-PyTorch 模型
  • WPF依赖属性学习
  • 云原生-高级阶段-利用rsync备份全网服务器数据
  • wordpress建购物网站抚顺营销型网站建设
  • Pythoner 的Flask项目实践-添加Shapefile面数据并展示功能Mapboxgl底图
  • Flutter混合Android开发Release 打包失败GeneratedPluginRegistrant.java,Plugin不存在
  • docker 安装TDengine 并创建新用户
  • 网站推广实施方案珠海网站制作软件
  • 为世界添彩 - WebGL 中的颜色与着色器变量
  • 初识MYSQL —— mysql的安装
  • c回顾 01
  • 【LeetCode 每日一题】3484. 设计电子表格——(解法一)二维数组
  • python+django/flask+springboot实践性教学系统 实训任务发布 学生作业提交 教师评阅管理系统
  • 洞悉未来,智驭不确定性:蒙特卡洛模拟决策模型实践
  • 长宁哪里有做网站优化比较好利润在100万到300万之间税率2021
  • 沈阳网站设计外包广西建设网官网桂建云
  • vscode 插件怎么实现编辑器行号处添加图标标记
  • Git 从零到一:以 Gitee 为例的实战与可视化指南
  • React 标准 SPA 项目 入门学习记录