Skip to content

Daily Study

更新: 6/19/2025 字数: 0 字 时长: 0 分钟

Daily Plan

#todo

  • [ ]

Mysql慢查询相关

与Redis延迟区分开!

发现慢查询

  • 开启慢查询日志
sql
-- 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';

-- 设置慢查询的阈值时间,单位为秒。例如,超过1秒的查询就算慢查询。
SET GLOBAL long_query_time = 1;

-- (可选,但强烈推荐) 记录没有使用索引的查询。这类查询通常是潜在的性能瓶颈。
SET GLOBAL log_queries_not_using_indexes = 'ON';
  • 使用工具进行日志分析:
    • mysqldumpslow:MySQL官方自带的工具,可以对慢查询日志进行分类、排序,找出最耗时的SQL。
    • pt-query-digest:Percona Toolkit中的一个强大工具,功能远超mysqldumpslow,能生成非常详细和专业的分析报告。
  • 查看当前线程监控:SHOW FULL PROCESSLIST 这个命令可以查看当前正在MySQL中执行的所有线程。如果某个线程的Time列数值很大,并且State不是Sleep,那么它很可能就是一条正在执行的慢查询。你可以据此找到对应的SQL语句并手动终止它(KILL [id];

分析慢查询

定位到SQL语句后,使用 EXPLAIN 进行分析

列名关键值解读优化方向
type性能从好到坏: system > const > eq_ref > ref > range > index > ALL
出现 ALL 是最坏的情况,表示MySQL正在进行全表扫描,即遍历表的每一行来查找匹配项。这是必须优化的信号。
尽量避免ALLindex,目标是优化到range或更好。
key实际使用的索引。如果这一列是 NULL,表示MySQL没有使用任何索引来执行查询。确保查询使用了最合适的索引。
rowsMySQL估算的为了找到结果,需要读取的行数。这个数字越大,查询通常越慢。通过索引或其他优化手段,减少需要扫描的行数。
Extra包含了非常重要的额外信息。
Using filesort:表示MySQL无法利用索引完成排序,不得不在内存或磁盘上进行额外的排序操作,性能开销极大。
Using temporary:表示MySQL需要创建一个临时表来处理查询,通常发生在GROUP BYUNION等操作中,同样非常耗费性能。
必须想办法消除Using filesortUsing temporary,通常通过创建合适的索引来解决。

慢查询优化

  • 索引优化:参照Mysql索引相关
  • SQL改写:
    • 避免SELECT *:只查询你需要的列,尤其是在大表上。这能减少网络传输量,并且更有可能用上覆盖索引。
    • 避免在索引列上使用函数或计算
      • WHERE YEAR(create_time) = 2025。这会导致索引失效。
      • WHERE create_time >= '2025-01-01' AND create_time < '2026-01-01'
    • 小表驱动大表:在多表JOIN时,尽量让结果集小的表作为驱动表。
    • 避免OR:在某些情况下,使用OR可能会导致索引失效。可以考虑用UNION ALL来代替。
    • 使用LIMIT:如果你只需要一部分数据,一定要使用LIMIT,尤其是在删除或更新大量数据时,分批处理。
  • 架构与设计层优化:
    • 引入缓存:对于读多写少的、非实时性要求高的数据,引入Redis或Memcached等缓存层,将热点数据放入缓存,极大减轻数据库压力。
    • 读写分离:对于读请求远大于写请求的场景,搭建主从复制架构,让主库负责写,多个从库负责读,分摊读压力。
    • 分库分表:当单表数据量达到千万甚至上亿级别时,需要考虑水平或垂直分片,将数据分散到不同的表或数据库中。

菜就多练

本站访客数 人次 本站总访问量