测试发现我们的一个接口存在性能问题,经分析是一个SQLMAP中一个SQL有两个层面的业务逻辑,用OR连接,如下所示。
select * from table_name where a='111' and b='222' and c='333' or d = '444';
此表中约有近100W的数据量,查看建表语句发现a、b、c是主键,而d字段未建索引。于是我立马想到的第步优化即在d上建索引。
一.索唯一索引
且从业务逻辑来看,d字段不会重复,因此给d字段建了唯一索引,给测试压测发现性能还是不行。
二.采用union all来替代or
分析业务,由于是进行重复情判断,因为从业务角度来讲,完全可以用union all来替代or,于是修改SQL如下:
select * from table_name where a='111' and b='222' and c='333'
union all
select * from table_name where d = '444';
再做性能分析,基本达到业务要求。
三.将以上SQL拆分成两条SQL语句
将以上SQL拆分成如下两条SQL语句:
select * from table_name where a='111' and b='222' and c='333';
select * from d = '444';
在应用层分开调用,再做性能分析,也基本达到业务要求。
四.SQL分析
1.explain select * from table_name where a='111' and b='222' and c='333' or d = '444';
2.explain select * from table_name where a='111' and b='222' and c='333' union all select * from table_name where d = '444';
3.explain select * from table_name where a='111' and b='222' and c='333';
4.explain select * from table_name where d = '444';
从SQL分析来看,主键和唯一索引在表中找到所需行的方式都为const,它表示当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。
system是const类型的特例,当查询的表只有一行的情况下,使用system。
五.Impossible WHERE noticed after reading const tables分析
换一个不存在的主键或唯一索引值,如如下SQL所示:
explain select * from table_name where d = 'aaa';
explain select * from table_name where a='aaa' and b='bbb' and c='ccc';
据说,这是因为mysql是首先对索引记录进行查询,然后在分析效果。
附:知识回顾
explain的type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL