xiaobaoqiu Blog

Think More, Code Less

Mysql优化

最近项目组遇到的慢查询比较多,大家的慢查询意识逐渐有了,同事做的工作中使用到的优化慢查询的方法分享,这里简单总结一些,便于以后使用。

通常这些优化方式是组合使用的。

1.合理使用索引

1.1 一个表只会使用一个索引

假设customer表有两个索引:

1
2
  KEY `idx_create_time` (`create_time`) USING BTREE,
  KEY `idx_city` (`city`)

sql语句的where条件包含create_time和city

1
explain select * from customer where city = 'beijing' and create_time > '2015-01-01';

这个sql语句只会走一个索引。

1.2 索引区分度越大越好

索引的区分读越大越好,可以使用show index from table看表的索引情况。

1.3 行数越少越好

执行计划中sql搜索的行数(rows)越小越好。

1.4 查询条件字段不要套函数,无法使用索引

比如下面这个sql是不走索引的

1
explain select * from customer where left(city, 2) = 'be';

2.不要复合条件查询

将复合条件根据规则转换为单个条件,避免多个字段去or。

比如我们在city上面建立了索引,但是我们没有在name上建立索引,下面这个sql会走全表而不走索引

1
explain select * from customer where city = 'beijing' or name = 'beijing';

3.减少join

利用Mybatis的动态SQL,保证同一时刻JOIN的表最少。即满足某一个条件的时候才join。

1
2
3
4
select * from customer
<if test="conditions.name != null and conditions.name != ''">
    join user on user.id = customer.user_id
</if>

4.分步查询

比如一个sql需要大量的join,并且每个join表的数据量都很大,这时候,尝试将单独的sql拆分成多个sql。

我们可以从搜索条件入手,不包含搜索条件的表一定可以拆分成单独的sql。

1
2
3
4
5
6
7
8
9
select *
from A
join B on ...
join C on ...
join D on ...
join E on ...
where
A.name = ...
and B.city = ...

这是可以考虑对C,D,E表的查询单独拆分出来。

5.合理使用Cache

通常根据条件Count比较耗时,可以将Count数Cache,比如list接口的count通常成千上万,count数只是用来展示页数,这时候可以考虑缓存下来,但是需要考虑好缓存策略。

6.业务逻辑上优化

当我们使用上述步骤无法优化时,可以考虑从逻辑上优化。

比如join很多个表查询的时候,我们需要确认应用方所有的字段都需要,通常减少字段能让我们少join表。