本博客借鉴《高性能mysql》
避免请求不需要的数据,减少服务器负担和网络开销
①避免向数据库查询不必要的数据,可以加上limit
②多表联查避免返回所有表的所有列。
③尽量不使用select *
④为查询重复的数据作缓存
切分查询
如果需要做一件很耗时的事,而且这事不是很急,可以把这个大的查询切分开来,把压力分散在很长的时间段中。
分解关联查询
一般分解关联查询应用在数据量大的时候
采用多次单表查询去分解
优势:提高缓存效率;减少锁竞争;更容易对数据库做拆分;
查询过程
①客户端发送给服务端一条查询
②服务端检查查询缓存
③服务器进行sql解析、预处理、优化生成相应执行计划
④根据执行计划调用存储引擎api进行查询
⑤返回结果
优化器
IN()比OR的性能高:
在mysql中,mysql将in列表中的数据先进行排序,然后进行二分查找,这是个O(logn)的操作,而OR查询是O(N)
在高性能mysql中列了很多优化器的操作,不过这条感触较深。
除此之外还有等价变换规则、预估并转化成常数表达式、覆盖索引扫描、子查询优化、提前终止查询、等值传播等。
我们可以在做查询前用EXPLAIN看查询计划,优化器会使用优化策略生成一个最优的执行计划。
关联查询
mysql认为任何一个查询都是一次“关联”。
可以简单的认为关联查询就是多重的for循环或者while循环。
关联查询优化器
优化器会对关联查询进行一定的优化。
有这么一个表结构进行多表关联,film表的记录有950条,actor表的记录有200条。
一种思路是先从film表找出所有film_id,然后嵌套循环从film_actor中根据索引film_id找到对应actor_id,最后找到actor中记录。
但是关联优化器会对关联顺序进行优化,先从actor表进行查询,这样只须对200条记录进行嵌套查询就行,但是之前的方法却要进行950次嵌套查询,所以效率不高。
子查询
例如select * from film where film_id in (select film_id from film_actor where actor_id=1);
按我们思路任务先会根据actor_id在film_actor表中查询,然后再去用in的优化。
但是mysql其实不是这样做的,mysql会改成如下的执行:
select * from film where exists (select film_id from film_actor where actor_id=1 and film_actor.film_id = film.film_id);
因为需要关联外表,所以会先对film进行全表查询,这样大大的减弱了性能。
所以我们可以将子查询改成关联查询,这样mysql会对关联查询的顺序进行优化。
但是并不是所有的子查询性能都不行,具体情况还得具体分析。
优化特定类型查询
count()
例如有很多城市,要检索id大于5的城市
可以用总数-小于等于5的城市。这样扫描的行数就少了
优化关联查询
如果A和B用c关联,如果优化器关联顺序为BA。那就就给A加索引,因为B肯定要取出所有的行,然后根据id在A中查找,这样就能利用A中索引。
优化limit
limit 10000 ,20这样的语句,虽然只要了20条,但是数据都查出来了,只是前面的一万条给丢弃了。最简单的办法就是索引覆盖扫描。
优化union
除非服务器需要消除重复的行,否则就用union all。如果没有all,mysql会加上distinct选项降低性能。