游乐游手机版
首页/数据库/文章详情

慢SQL产生原因有哪些?如何定位并优化慢查询

时间:2026-08-24 15:09
慢SQL慢SQL通常是指执行耗时超过预设阈值的 SQL 语句,该阈值一般由long_query_time参数控制,默认值为10秒。定位可以通过在配置文件my cnf的[mysqld] 下添加以下配置来开启慢查询日志(重启后依然生效):[mysqld] slow_query_log=1 开启慢查询

慢SQL

慢SQL通常是指执行耗时超过预设阈值的 SQL 语句,该阈值一般由long_query_time参数控制,默认值为10秒。

慢SQL是什么原因导致的?如何定位和优化慢查询

定位

  • 可以通过在配置文件my.cnf的[mysqld] 下添加以下配置来开启慢查询日志(重启后依然生效):
[mysqld] slow_query_log=1 //开启慢查询日志slow_query_log_file=/var/lib/mysql/mysql-slow.log //慢查询日志存放路径   long_query_time=3 //慢查询阈值log_output=FILE 

也可以通过在mysql客户端执行命令临时开启(重启后失效),如下:

SET GLOBAL slow_query_log = ‘ON';SET GLOBAL slow_query_log_file = ‘/var/lib/mysql/mysql-slow.log';SET GLOBAL long_query_time = 3;

分析

通过执行 EXPLAIN,在对应SQL前加上 EXPLAIN 后,即可查看该SQL的执行计划,示例如下:

    id  select_type  table    partitions  type    possible_keys  key       key_len  ref       rows  filtered  Extra        ------  -----------  -------  ----------  ------  -------------  --------  -------  ------  ------  --------  -------------     1  SIMPLE       student  (NULL)      index   (NULL)         name_age  68       (NULL)      10    100.00  Using index  

分析执行计划时,主要关注 type、key、rows、extra

type

表示本次执行该SQL时所使用的访问类型或索引扫描方式

索引类型的效率:

NULL > system > const > eq_ref > ref > ref_or_null > index_merge > range > index > ALL,这是常见的性能排序顺序。

  • NULL表示该SQL不需要实际访问表,或者获取的是索引的最大值或最小值(只需访问索引叶子节点的左端或右端)

  • system表示该SQL访问的表中只有一行记录

  • const表示该SQL使用主键索引或唯一索引,通常只需一次索引查找即可定位记录

  • eq_ref表示该SQL使用了join关联查询,并且能够通过主键索引或唯一索引定位唯一记录

  • ref表示可以通过非唯一索引查找到匹配记录

  • ref*_or_null *表示在ref的基础上,索引列还支持null值匹配

  • index_merge表示使用了多个索引进行组合查询(通常不是联合索引)

range 表示使用索引列进行范围条件查询,如

=, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN

  • index 表示使用索引进行了全索引扫描

  • all 表示未使用索引,直接进行全表扫描

key

表示实际命中的索引名称(即建立索引时定义的名称),如果没有使用索引则为NULL

rows

表示mysql预估该SQL通过索引访问时需要读取到server层的数据行数。对于同一条SQL来说,不同索引下该值越小,通常说明索引效果越好

filtered

表示预估读取到server层后,没有被过滤掉的数据行比例,即 n/rows*100%

extra

表示mysql执行过程中的额外优化信息

  • using index:使用了覆盖索引
  • using where:需要回表后再根据where条件进行数据过滤
  • using index condition :使用了索引下推
  • using temporary:使用了临时表,常见于聚合函数、子查询等还需要进一步处理数据的SQL
  • using filesort: 对结果集进行了排序,但没有使用到索引(索引失效)或缺少对应索引

索引优化

最左前缀匹配

建立联合索引时,索引字段顺序通常需要结合使用频率、字段区分度以及范围查询(可能导致后续索引失效)来综合判断

如 SQL:

select * from student where score=60 and finished_time >'2000-10-10'

建立索引

idx_score_finished(score,finished)

注:具体仍需结合实际业务场景进行判断

索引覆盖

对于高频查询、返回字段较少的SQL,可以考虑建立联合索引来实现覆盖索引,从而减少回表次数,提升查询性能

如 SQL:

select name,score from student where finished_time ='2000-10-10'

建立索引

idx_finished_name_score

索引下推

可以针对查询条件建立合适索引,以减少回表到server层后再过滤的数据行数。需要注意的是,当查询条件中的索引无法生效,或者根本没有可用索引时,数据只能传到server层再做过滤处理,这往往会增加SQL执行成本。

如 SQL:

select score from student where name ='stu' and finished_time ='2000-10-10'

建立索引

idx_name_finished

表结构优化

数据类型

如果可以确定该列不会为NULL(并且有默认值),设置not null能够节省部分存储空间,同时有助于提升查询效率

数字类型

  • 根据数值范围选择tinyint、int、bigint,避免存储空间浪费。若确认数值不存在负数,优先选择unsigned
  • double类型在计算时可能存在精度丢失问题,可根据业务改为int类型,由业务层处理小数,或者直接使用decimal

字符类型

  • 尽量避免滥用text类型
  • 对于定长字符或长度差异不大的字段,使用char有时更合适,能够节省一部分额外存储开销(省去varchar的len部分)
  • varchar长度应根据业务需求合理设计,过长会导致行数据读入内存时消耗更大

日期类型

  • 如果时间范围在1970-2038之间且没有特殊要求,可优先使用timestamp,在相同精度下其存储空间约为datetime的一半
  • 如果只需要保存到日,也可以使用datetime,只需3字节

字符编码

如果对字符兼容性要求不高,可以不一定选择utf等相对冗余的编码方式,建议按实际需求选择字符集

注:存在联表关系的表中,表间关联字段的字符集应保持一致,避免关联时因字符集不同而导致索引失效

​​范式与反范式平衡

可以根据业务场景适当进行反范式设计,也就是增加冗余字段,以减少关联查询开销

如: product表 kind表 可在product表上冗余kind_name字段

像text这类大字段会影响数据行加载到内存页的速度(大字段可能发生行溢出,带来额外磁盘IO),可以考虑拆分到单独表中,再通过关联方式读取

SQL优化

  1. 按需SELECT,避免使用SELECT*,减少网络IO和带宽消耗
  2. 索引字段要避免MySQL隐式类型转换,例如bigint类型的id应传int64而不是字符串,防止索引失效
  3. like查询尽量避免把通配符放在左侧,否则不符合最左前缀匹配原则,容易导致索引失效
  4. 避免在索引列上使用mysql内置函数(server层处理),否则可能导致索引无法命中
  5. 避免对索引列进行计算或运算操作
  6. 索引列做等值查询时,优先使用=,而不是<>
  7. 多表操作如join、in等,尽量使用小表驱动大表的写法,减少关联数据量
  8. 批量操作建议在业务层分批处理,再通过SQL批量执行,减少高并发插入带来的锁竞争
  9. 合理使用limit减少单次返回的数据行数和回表行数,从而降低网络IO与SQL执行时间
  10. 深分页可以采用延时分页优化:先查出符合条件的id并limit,再回主表关联查询,减少不必要的二次回表成本

总结

以上内容是关于慢SQL定位、慢查询分析以及MySQL优化的一些个人经验总结,希望能为大家排查和优化慢查询提供参考,也欢迎大家继续支持本站。

来源:https://www.jb51.net/database/3695581ip.htm
上一篇Oracle RMAN报ORA-19815告警的处理方法与解决步骤 下一篇phpMyAdmin导入SQL排序规则错误的修复方法
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
Redis是什么:核心特性、架构与应用场景解析
数据库 · 2026-09-01

Redis是什么:核心特性、架构与应用场景解析

Redis是一款基于内存的键值型NoSQL数据库,以超高读写速度和丰富的数据结构著称。本文系统梳理Redis的核心特性、架构组成、性能优势及典型应用场景,并通过与Memcached、MySQL、MongoDB的对比,帮助开发者快速判断Redis是否适合当前业务需求。

Windows 安装 MongoDB 完整图文教程
数据库 · 2026-09-01

Windows 安装 MongoDB 完整图文教程

本文详细介绍在 Windows 系统上安装 MongoDB 的完整流程。从官网下载 MSI 安装包开始,逐步演示自定义安装路径、配置 Windows 服务、跳过 MongoDB Compass 等关键选项,并提供通过系统服务列表验证安装是否成功的方法,帮助开发者快速搭建本地 MongoDB 环境。

Linux 安装 MongoDB 完整指南:依赖配置、环境变量与服务启动
数据库 · 2026-09-01

Linux 安装 MongoDB 完整指南:依赖配置、环境变量与服务启动

本文详解在 Linux 系统下安装 MongoDB 的完整流程,涵盖依赖包安装、二进制包下载解压、环境变量配置、数据与日志目录创建及服务启动验证。通过标准化命令与路径说明,帮助开发者快速完成部署并确认服务状态。

MacOS安装MongoDB完整教程
数据库 · 2026-09-01

MacOS安装MongoDB完整教程

本文介绍在MacOS系统下安装MongoDB的完整流程,涵盖下载、解压、目录配置、环境变量设置及服务启动。通过明确的命令与参数说明,帮助开发者快速完成环境搭建并验证安装结果。

Ubuntu系统安装与配置Redis完整指南
数据库 · 2026-09-01

Ubuntu系统安装与配置Redis完整指南

本文详解在Ubuntu系统中安装Redis的两种主流方式:apt在线安装与源码编译安装。涵盖版本选择逻辑、服务启停与状态检查、连接验证方法,以及在线练习工具与桌面GUI客户端的对比与使用建议,帮助开发者快速搭建并验证Redis运行环境。