SQL查询慢怎么查_慢SQL定位与优化流程

10次阅读

sql 查询优化需分三步:先开启慢查询日志定位问题 sql,再用 explain 分析执行计划识别瓶颈(如 type=all、key=null),最后针对性建联合索引、避免索引失效并验证效果。

SQL 查询慢怎么查_慢 SQL 定位与优化流程

SQL 查询慢,核心要分三步走:先抓出来,再看为什么慢,最后动手改。不盲目加索引,也不靠猜——整套流程有迹可循、可复现、可验证。

一、开启并获取慢查询日志

慢 SQL 得先“看见”,否则优化无从谈起。MySQL 默认关闭慢查询日志,需主动启用:

  • 临时开启(当前实例有效,重启失效):
    SET GLOBAL slow_query_log = ON;
    SET GLOBAL long_query_time = 1;(建议设为 1 秒,生产环境可调至 0.5 秒)
    SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
  • 永久生效:修改 my.cnf[mysqld] 段,加入
    slow_query_log = 1
    slow_query_log_file = /var/log/mysql/slow.log
    long_query_time = 1
    log_queries_not_using_indexes = 1(辅助发现隐性低效 SQL)
  • 验证是否生效:
    SHOW VARIABLES LIKE 'slow_query_log';
    SHOW STATUS LIKE 'Slow_queries';(该值会随慢 SQL 执行递增)

二、用 EXPLAIN 看清执行计划

日志里找到慢 SQL 后,别急着改,先运行 EXPLAIN + SQL,重点盯这几个字段:

  • type:越靠前越好(constref > range > index > ALL)。出现 ALL 基本等于全表扫描。
  • key:实际命中哪个索引?显示 NULL 就是没走索引。
  • rows:预估扫描行数。百万级表扫几十万行,大概率有问题。
  • Extra:警惕 Using filesort(额外排序)、Using temporary(建临时表)、Using join buffer(关联缓存不足)。

例如对订单表查用户 + 时间范围:
SELECT id, order_no FROM tb_order WHERE user_id = 10086 AND create_time >= '2025-01-01' AND delete_flag = 0;
EXPLAIN 显示 type=ALLkey=NULL,说明现有 idx_user_id 单列索引无法覆盖 create_timedelete_flag 条件。

三、针对性优化常见路径

90% 的慢 SQL 问题落在索引和写法上,优先检查这几类:

  • 补联合索引 :按查询条件顺序建,遵循最左前缀。上例可建:
    ALTER TABLE tb_order ADD INDEX idx_user_del_time (user_id, delete_flag, create_time);
    注意字段顺序:等值条件(user_iddelete_flag)放前,范围条件(create_time)放最后。
  • 避免索引失效
    ✅ 正确:WHERE create_time >= '2025-01-01'
    ❌ 失效:WHERE DATE(create_time) = '2025-01-01'(函数导致索引无法下推)
    ✅ 正确:WHERE status IN (1,2)
    ❌ 高风险:WHERE status != 0(可能跳过索引)
  • 减少数据传输量 :只查必要字段,避免 SELECT *;大分页用游标或延迟关联,别用 LIMIT 1000000, 20

四、辅助手段与验证闭环

光改完不行,得确认效果落地:

  • PROFILING 查耗时分布(开启后执行 SQL,再 SHOW PROFILE FOR QUERY N;),看是 I / O 卡住还是 CPU 计算拖慢。
  • 对比优化前后 EXPLAINrowstype,必须有明显下降才算有效。
  • 上线前在从库或压测环境实测 QPS、响应时间、CPU/IO 负载变化,避免“优化后更慢”。

慢 SQL 不是单点问题,而是数据库、SQL 写法、索引设计、甚至业务模型的综合反馈。定位准、分析透、改得稳,才能真正把性能攥在手里。

text=ZqhQzanResources