Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL查询速度提高方案

MySQL提高查询速度的常见方案及避坑指南

作者:detayun

MySQL 查询慢是后端开发最常遇到的问题,很多人遇到慢SQL第一反应就是加索引,但索引不是万能解药,本文从原理到实战,梳理MySQL查询优化整套思路,需要的朋友可以参考下

前言

MySQL 查询慢是后端开发最常遇到的问题。很多人遇到慢SQL第一反应就是加索引,但索引不是万能解药,不合理的索引、糟糕的SQL写法、不当的表结构,依旧会导致全表扫描。
本文从原理到实战,梳理MySQL查询优化整套思路,覆盖索引、SQL编写、表设计、配置、业务架构层面,附带常见踩坑案例,适合开发自查慢查询。

环境:MySQL5.7 / 8.0,InnoDB引擎。

一、先找到慢SQL:优化的前提

优化不是凭感觉,第一步是定位慢查询。

1. 开启慢查询日志

-- 查看慢查询配置
SHOW VARIABLES LIKE 'slow_query_log%';
SHOW VARIABLES LIKE 'long_query_time';

2. explain 分析执行计划

EXPLAIN 是最核心工具,放在SELECT前面,看SQL如何执行。

EXPLAIN SELECT * FROM user WHERE phone = '13800138000';

重点看这几个字段:

  1. type:访问类型,性能从优到劣:system > const > eq_ref > ref > range > index > ALL,ALL代表全表扫描,需要优化
  2. key:实际使用的索引,NULL代表没有用到索引
  3. rows:预估扫描行数,数值越大越危险
  4. Extra:额外信息,Using filesort(文件排序)、Using temporary(临时表)都是性能杀手

优化目标:尽量避免 type=ALL,消除 Using filesort、Using temporary。

二、索引优化:提升查询最核心手段

InnoDB是B+树索引,索引的本质是减少扫描行数。

1. 最左前缀原则(联合索引重中之重)

联合索引 idx_a_b_c(a,b,c),生效顺序:从左往右匹配,遇到范围查询(> < like %xx)停止。
✅ 可以命中索引:
where a=?、where a=? and b=?、where a=? and b=? and c=?
❌ 无法命中:
where b=?、where c=?,跳过最左列,索引失效。

建索引顺序原则:等值条件放前面,范围条件放最后。

2. 索引失效常见场景(高频踩坑)

  1. 索引列参与运算、函数操作
-- 失效!索引列做函数
SELECT * FROM user WHERE DATE(create_time) = '2026-10-01';
-- 改写,把函数移到常量一侧
SELECT * FROM user WHERE create_time >= '2026-10-01' AND create_time < '2026-10-02';
  1. 隐式类型转换:字符串字段用数字查询
-- phone是varchar,传入数字,触发隐式转换,索引失效
SELECT * FROM user WHERE phone = 13800138000;
  1. LIKE '%关键词',前缀模糊匹配,索引失效;LIKE '关键词%' 可以走索引
  2. OR 两边字段有一方无索引,整个索引失效
  3. 优化器判断全表扫描更快,主动放弃索引(数据量占比过高)

3. 不要盲目建索引

索引优点:加快查询;缺点:占用磁盘,降低写入性能(INSERT/UPDATE/DELETE要维护索引)。

4. 覆盖索引(避免回表)

InnoDB二级索引叶子节点存主键,查到索引后需要回主键索引读取完整行,叫回表。
覆盖索引:索引包含查询需要的所有字段,不需要回表,性能极高。

-- 需求:只查id,username,phone
-- 建立联合索引 idx_username_phone (username, phone)
SELECT id,username,phone FROM user WHERE username='zhangsan';

Explain Extra列会出现 Using index,代表命中覆盖索引。

三、SQL写法优化:改掉坏习惯

1. 禁止SELECT *

只查询业务真正需要的字段。

2. 分页大偏移优化

OFFSET 100000 LIMIT 10,会先扫描10万行再丢弃,性能极差。
❌ 低效写法

SELECT * FROM order LIMIT 100000,10;

✅ 主键书签优化(推荐)

SELECT * FROM order WHERE id > 100000 LIMIT 10;

如果主键不连续,也可以用子查询先定位主键:

SELECT t.* FROM order t
INNER JOIN (SELECT id FROM order ORDER BY id LIMIT 100000,10) AS tmp ON t.id = tmp.id;

3. 优化JOIN关联查询

  1. 小表驱动大表,INNER JOIN 优化器会自动选择,但尽量保证关联字段建立索引;
  2. JOIN字段类型、字符集必须一致,防止隐式转换;
  3. 避免多表JOIN,超过3张表关联建议业务层拆分;
  4. 不要在子查询里写大表,EXISTS 适合大表,IN 适合小集合。

原则:IN 集合数量不要过大,建议控制在1000以内。

4. 排序与分组优化

ORDER BY、GROUP BY 尽量利用索引有序特性,避免 Using filesort。

四、表结构设计优化(从源头减少慢查询)

1. 字段类型选择,越小越好

2. 主键设计

InnoDB主键是聚簇索引:

3. 分表分区

单表数据量千万级以上,索引体积变大,查询性能下降。

注意:分区、分表会增加业务复杂度,不要过早优化。

五、MySQL配置层面调优

核心参数(根据服务器内存调整)

  1. innodb_buffer_pool_size:最重要参数,InnoDB缓存池,推荐服务器物理内存的50%~70%,缓存索引和数据页,减少磁盘IO;
  2. innodb_log_file_size:redo log大小,提升写入性能;
  3. sort_buffer_size、join_buffer_size:会话级缓存,不要设置过大,容易内存溢出;
  4. max_connections:连接数,按需调整,不要盲目开大。

调优原则:优先调 innodb_buffer_pool_size,大部分性能瓶颈是磁盘IO。

六、业务架构层面优化(终极方案)

当SQL、索引、参数优化到极限,还慢,就要考虑架构方案:

  1. 读写分离:主库写,从库承担查询压力;
  2. 缓存:热点数据放Redis,拦截高频查询,直接绕开MySQL;
  3. 预计算:报表、统计类查询不要实时查MySQL,定时预计算结果存入汇总表;
  4. 搜索引擎:全文检索、多条件复杂检索,迁移到Elasticsearch,减轻MySQL压力。

七、常见误区

  1. 索引越多查询越快:错,索引会拖慢写入;
  2. EXPLAIN看到索引就一定很快:要看扫描rows,索引区分度差依旧慢;
  3. 调优只改参数,不改SQL:绝大多数慢查询根源是SQL和索引;
  4. 用缓存就不用优化SQL:缓存失效瞬间,大量请求打满数据库,雪崩风险。

八、优化通用步骤总结

  1. 开启慢查询日志,捕获慢SQL;
  2. EXPLAIN分析执行计划,定位全表扫描、文件排序;
  3. 优化SQL写法,调整索引,优先利用覆盖索引;
  4. 优化表结构,精简字段;
  5. 调整MySQL核心配置;
  6. 业务层引入缓存、读写分离、分表等架构方案。

小结

MySQL查询优化是分层的:优先优化SQL和索引,其次优化表结构,再调整数据库参数,最后才考虑架构改造。
很多时候一个不合理的WHERE条件、失效的索引,就足以让数据库性能下降几十倍。优化前一定要用explain验证,不要凭经验猜测。

以上就是MySQL提高查询速度的常见方案及避坑指南的详细内容,更多关于MySQL查询速度提高方案的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文