MySQL性能调优
一、EXPLAIN
EXPLAIN 是用于查看 SQL 查询执行计划的工具,它帮助分析 SQL 语句的执行过程,包括是否使用了索引、是否需要外部排序、是否使用了索引覆盖等。
1、执行计划参数
possible_keys:优化器评估的候选索引列表;
key:实际使用的索引,如果为 NULL,表示未使用索引;
key_len:使用的索引长度(字节数);
rows:优化器预估的扫描行数;
type:数据扫描的方式,需要重点关注;
extra:执行计划的额外信息,指示扫描过程中使用的优化方法;
2、type 字段的常见扫描类型
执行效率从低到高:
ALL:全表扫描,这是最差的执行方式,因为需要扫描整个表;
INDEX:全索引扫描,虽然通过索引扫描,但依然需要读取整个索引,效率较低;
RANGE:索引范围扫描,通常用于 WHERE 子句中带有 <、>、IN、BETWEEN 等操作符,扫描索引范围,效率较高;
REF:非唯一索引扫描,适用于非唯一索引或唯一索引的非唯一前缀,返回的可能是多条记录,效率较高;
EQ_REF:唯一索引扫描,通常在多表连接时使用,效率很高;
CONST:常量查询,通常用于主键或唯一索引查询,返回结果只有一行,效率最高;
3、extra 字段的常见标志
Using filesort:表示 MySQL 在查询时使用了外部排序,通常出现在 GROUP BY 或 ORDER BY 操作中,效率较低;
Using temporary:表示 MySQL 使用了临时表来存储中间结果,常见于 GROUP BY 或 ORDER BY,效率较低;
Using index:表示查询只通过索引获取数据,而不需要访问表本身,这称为索引覆盖,效率较高,避免了回表操作;
二、性能优化方案
1、定位性能瓶颈
a. 查看slow_query_log(慢查询日志)锁定慢sql;
b. 并结合EXPLAIN命令分析SQL的执行计划,找出慢查询的原因;
2、索引设计与优化
a. 为查询中的 WHERE 子句、JOIN 操作、ORDER BY 和 GROUP BY 子句中的字段创建索引;
b. 对于多个字段经常同时出现在查询条件中的情况,创建联合索引(复合索引)。创建联合索引时遵循最左匹配原则,例如,查询 WHERE a = ? AND b = ? 时,创建 (a, b) 的复合索引会更高效;并且联合索引的字段顺序最好按区分度从高到低排列(如身份证号>姓名>性别)。
c. 避免对索引列使用函数、表达式、否定条件或模糊查询(如 LIKE '%xxx'),这些操作会导致索引失效,影响性能;
3、查询逻辑优化
a. 避免使用SELECT *,只查询真正需要的列;
b. 使用覆盖索引,即索引包含所有查询的字段,避免回表;
c. 联表查询最好要以小表驱动大表,并且被驱动表的字段要有索引,当然最好通过冗余字段的设计,避免联表查询;
d. 避免多层嵌套子查询(如SELECT * FROM (SELECT * FROM user WHERE status=1) t WHERE age>20),可改为JOIN或平铺查询逻辑;
e. 用EXISTS替代IN(当子查询结果集大时,EXISTS效率更高;结果集小时IN更优);
4、深分页优化
对于 LIMIT n, y(深分页)的查询,可能会出现性能下降的问题,特别是在数据量较大的情况下。
a. 用 “位置定位” 替代偏移量,如SELECT * FROM tb WHERE id > 20000 LIMIT 10,这样可以直接定位到 20000 后的行,无需扫描前置数据;
b. 用 “覆盖索引 + 书签查询”,如SELECT * FROM tb WHERE id IN (SELECT id FROM tb WHERE status=1 LIMIT 20000, 10),先通过索引查id,再回表查详情;
5、大表优化
如果单表的数据超过了千万级别,考虑是否需要将大表拆分为小表,减轻单个表的查询压力。
a. 水平分表(按行拆分):按业务维度拆分(如order_202401、order_202402按月份分表),或按哈希拆分(如user_0、user_1按user_id%2拆分);
b. 垂直分表(按列拆分):将高频字段(如id、name、status)和低频字段(如remark、create_log)拆分为两张表,避免查询时加载冗余字段;
6、使用缓存技术
使用缓存(如 Redis)来存储热点数据和频繁查询的结果,从而减少数据库的压力;
7.其他优化方案
a. 对于非常大的系统,可以考虑数据库分库分表,将不同的数据库实例分布到不同的物理服务器上,从而提升系统的横向扩展能力;
b. 数据库参数优化:连接池(max_connections)、缓冲区(innodb_buffer_pool_size、query_cache_size)、日志(binlog_cache_size)等参数调优;
c. 读写分离:通过主库写、从库读(如 MGR / 主从复制)分摊压力,是高并发场景的基础优化;
d.硬件优化;