一次具体的sql优化经历 (7个提升sql性能的方法)

1. 尽量避免使用子查询,例:

SELECT * FROM t1 WHERE id =(SELECT id FROM t2 WHERE name = 'peiqi');

2. 用IN来替换OR

低效查询:SELECT * FROM t WHERE id = 10 OR id = 20 OR id = 30;
高效查询:SELECT * FROM t WHERE id IN (10,20,30);

3. 读取适当的记录LIMIT M,N,而不要读多余的记录

select id,name from t limit 10000, 20

使用上述sql语句做分页的时候,可能有人会发现,随着表数据量的增加,直接使用limit分页查询会越来越慢。

对于 limit m, n 的分页查询,越往后面翻页(即m越大的情况下)SQL的耗时会越来越长,对于这种应该先取出主键id,然后通过主键id跟原表进行Join关联查询。因为MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。

优化的方法如下:可以取前一页的最大行数的id(将上次遍历到的最末尾的数据ID传给数据库,然后直接定位到该ID处,再往后面遍历数据),然后根据这个最大的id来限制下一页的起点。比如此列中,上一页最大的id是866612。sql可以采用如下的写法:

select id,name from table_name where id> 10000 limit 20

4. 禁止不必要的Order By排序

如果我们对结果没有排序的要求,就尽量少用排序;

如果排序字段没有用到索引,也尽量少用排序;

另外,分组统计查询时可以禁止其默认排序

SELECT goods_id,count(*) FROM t GROUP BY goods_id;

默认情况下,Mysql会对所有的 GROUP BT col1,col2… 的字段进行排序,也就是说上述会对 goods_id进行排序,如果想要避免排序结果的消耗,可以指定 ORDER BY NULL 禁止排序:

SELECT goods_id,count(*) FROM t GROUP BY goods_id ORDER BY NULL

5. 总和查询可以禁止排重用union all

union和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。

当然,union all的前提条件是两个结果集没有重复数据。所以一般是我们明确知道不会出现重复数据的时候才建议使用 union all 提高速度。

6. 避免随机取记录

SELECT * FROM t1 WHERE 1 = 1 ORDER BY RAND() LIMIT 4;
SELECT * FROM t1 WHERE id >= CEIL(RAND()*1000) LIMIT 4;