最近公司项目有几个逻辑运行的比较慢,于是通过对其执行的 SQL 进行分析,优化部分实现,以满足性能的要求,这里简单记录一下优化的过程和方法。

初步分析

1.首先找到需要优化的 SQL
云数据库一般都有提供慢 SQL 的页面
自己搭建的数据库就相对比较麻烦了,需要修改 my.cnf 中相关的配置文件来开启慢 SQL 记录功能。

2.分析慢 SQL
筛选出有问题的 SQL,我们可以使用 MySQL 提供的 explain 查看 SQL 执行计划情况(关联表,表查询顺序、索引使用情况等)。

1
explain select * from xxxTable;

返回结果:

1
2
3
4
5
6
7
mysql> explain select * from xxxTable;
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | xxxTable | NULL | ALL | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

关键的是 type 这一列
type:表的连接类型,其值,性能由高到底排列如下:
system:表只有一行记录,相当于系统表
const:通过索引一次就找到,只匹配一行数据
eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常用于主键或唯一索引扫描
ref:非唯一性索引扫描,返回匹配某个单独值的所有行。用于=、< 或 > 操作符带索引的列
range:只检索给定范围的行,使用一个索引来选择行。一般使用between、>、<情况
index:只遍历索引树
ALL:全表扫描,性能最差

调整相应的 SQL 语句以满足高效的执行效率。

优化方法

语法方面

1) 避免 SELECT *,需要什么数据,就查询对应的字段。
2) 小表驱动大表,即小的数据集驱动大的数据集。如:以 A,B 两表为例,两表通过 id 字段进行关联。
3) 一些情况下,可以使用连接代替子查询,因为使用 join,MySQL 不会在内存中创建临时表。
4) 适当添加冗余字段,减少表关联。
5) 合理使用索引。

数据库表结构设计

1) 使用可以存下数据最小的数据类型
2) 使用简单的数据类型。int 要比 varchar 类型在mysql处理简单
3) 尽量使用 tinyint、smallint、mediumint 作为整数类型而非 int
4) 尽可能使用 not null 定义字段,因为 null 占用4字节空间
5) 尽量少用 text 类型,非用不可时最好考虑分表
6) 尽量使用 timestamp 而非 datetime
7) 单表不要有太多字段,建议在 20 以内

数据库参数

如果是云服务器的话,这一步就不用做了,云服务器都是由服务器提供商进行优化的。
自己搭建的数据库的话可以参照网上教程进行优化。

硬件优化

1)提升内存空间
2)提高硬盘的 IO 读取速度,比如说由机械硬盘更换成 SSD
3)提高 CPU 的处理性能