慢 sql 的排查和优化是数据库性能调优的关键环节,尤其是在高并发环境下,慢 sql 可能会导致性能瓶颈,影响应用响应速度。以下是关于如何排查和优化慢 sql 的详细步骤。
一、如何排查慢 sql
1.开启慢查询日志
mysql 提供了慢查询日志功能,可以帮助我们识别执行时间较长的 sql 查询。
启用慢查询日志:
set global slow_query_log = 'on'; -- 开启慢查询日志 set global slow_query_log_file = '/path/to/your/slow_query.log'; -- 设置日志文件路径 set global long_query_time = 1; -- 设置记录慢查询的阈值,单位秒(1秒以上的查询会被记录)
查看慢查询日志内容:
查看日志文件,通常包含查询时间、sql 语句等信息。
cat /path/to/your/slow_query.log
2.使用explain语法分析 sql 执行计划
explain 可以展示 mysql 如何执行一个查询,它可以帮助你分析查询性能瓶颈。
explain select * from your_table where condition;
explain 的结果列包括:
- id:查询的标识符。
- select_type:查询的类型(如
simple、primary、union)。 - table:查询涉及的表。
- type:连接类型,表示查询的访问方式(如
all、index、range)。 - key:使用的索引。
- rows:mysql 执行查询时扫描的行数。
- extra:额外的信息,提示是否使用了文件排序(
using filesort)或临时表(using temporary)等。
3.使用show processlist查看当前查询
查看当前正在执行的查询,以便了解哪些查询可能会导致系统负载过高。
show processlist;
会返回正在执行的查询、线程 id、状态等信息,特别是 state 和 info 字段,能帮助判断哪些查询正在消耗时间。
4.查看数据库状态和性能指标
查看数据库的运行状态和各项性能指标,比如缓冲池的使用情况、i/o 性能等,可以帮助判断慢查询的原因。
show status like 'innodb_buffer_pool%'; show status like 'qcache%'; show status like 'handler_read%';
这些命令能够给出关于缓存、i/o、查询缓存的详细信息。
二、慢 sql 优化方法
1.分析和优化查询语句
(1)避免全表扫描
全表扫描通常是查询缓慢的原因之一。通过合理的索引设计,确保查询尽量通过索引来执行。
- 例如,避免使用
select *,只选择需要的字段。 - 确保
where子句中的条件列有索引。
(2)避免使用不必要的join
对于查询中涉及多个表时,减少 join 的次数和复杂度。尤其要注意,使用不合理的 join 会导致大量的数据中间结果集,影响查询性能。
- 避免使用多次
join:如果多个表之间没有必要联接,就不必使用join。 - 使用适当的连接顺序:在
join时,优先连接那些数据量小、过滤条件明确的表。
(3)避免在查询中使用函数和表达式
在 where 条件中对列进行函数操作(如 year(date)、lower(name) 等)会导致 mysql 无法利用索引。
例如:
select * from orders where year(order_date) = 2025;
如果在 order_date 上没有合适的索引,这样的查询会导致全表扫描。
2.合理使用索引
(1)索引优化
- 确保常用的查询字段(尤其是
where子句、join条件、order by和group by字段)都有适当的索引。 - 对于范围查询(如
between、>、<)字段,应该确保索引的顺序符合最左前缀原则。
(2)避免索引失效
- 避免对索引列做计算或函数操作,如
where year(date) = 2025。 - 使用覆盖索引,当查询的字段都包含在索引中时,索引就可以返回查询结果,无需回表。
create index idx_name on users(name, email);
如果查询时仅涉及 name 和 email 字段,索引就可以直接返回结果。
(3)减少索引的数量
过多的索引会影响写入性能,尤其是在 insert、update 或 delete 操作时。应根据查询的频率和类型合理选择索引。
3.合理使用数据库缓存
(1)调整innodb缓冲池大小
innodb 存储引擎使用缓冲池缓存数据和索引。适当增大缓冲池的大小可以减少磁盘 i/o,提高查询性能。
set global innodb_buffer_pool_size = <size>;
(2)使用查询缓存
虽然在 mysql 5.7 后已弃用查询缓存,但在适用的场景下,开启查询缓存仍能提高查询性能。
set global query_cache_size = <size>;
(3)调整sort_buffer_size和read_buffer_size
这些参数影响排序操作和全表扫描操作的内存使用。适当增大这些值,可以减少磁盘 i/o,提高查询效率。
set global sort_buffer_size = <size>; set global read_buffer_size = <size>;
4.优化表结构和分区
(1)表分区
当表非常大时,使用分区可以提高查询性能。表分区会根据某个列的值将数据分到不同的物理存储区域,这样可以减少每次查询时的数据扫描量。
(2)避免表的过度设计
例如,避免在同一个表中存储过多的历史数据,定期归档过期的数据。对于长期不更新的数据,可以使用更为高效的存储方式(例如将历史数据迁移到冷数据存储)。
5.分页查询优化
分页查询通常会出现性能问题,尤其是当页数很大时。优化方法包括:
- 使用
limit和offset时,确保有合适的索引,避免大范围的全表扫描。 - 使用
where子句限制记录范围,如按时间戳或 id 排序,避免使用不索引的字段进行分页。
select * from orders where order_date >= '2025-01-01' limit 100 offset 1000;
6.减少网络带宽消耗
对于返回大量数据的查询,减少返回的数据量也是一个优化点。只查询必要的字段,避免 select *。
7.考虑读写分离
对于数据库的高并发访问,读写分离可以通过将读操作和写操作分配到不同的数据库实例,来分担数据库负载,从而优化查询性能。
三、背诵版
慢 sql 排查:
- 开启慢查询日志:
set global slow_query_log = 'on'; - 使用
explain分析执行计划:查看是否有全表扫描、索引扫描等。 show processlist查看当前执行的查询:找到耗时较长的查询。- 查看 mysql 状态信息:如
show status like 'innodb_buffer_pool%',分析缓存和 i/o 使用情况。
慢 sql 优化方法:
优化查询语句:
- 避免全表扫描。
- 合理使用
join和子查询。 - 不要在查询条件中使用函数或表达式。
优化索引:
- 为常用查询字段添加合适的索引。
- 使用覆盖索引避免回表。
- 减少不必要的索引。
缓存优化:调整 innodb 缓冲池大小,合理使用查询缓存。
分页查询优化:避免大页数的 offset 分页,限制查询范围。
读写分离:通过数据库主从分离,减轻数据库压力。
到此这篇关于mysql慢查询排查和优化的详细步骤教学的文章就介绍到这了,更多相关mysql慢查询优化内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论