Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > Mysql优化查询速度

Mysql如何优化查询速度

作者:哇~是小菜呀

这篇文章主要介绍了Mysql如何优化查询速度问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

对于需要排序的字段使用索引

当查询结果需要order by的时候,可以在order by 的字段加上索引,因为索引已经排列好顺序了,

所以可以更快的完成排序,而不需要每次对查询结果进行排序,耗费大量内存和时间。

尽量使用union all 而不是union

除非确实需要服务器消除重复的行,否则一定要使用union all,因此没有all关键字,

mysql会在查询的时候给临时表加上distinct的关键字,这个操作的代价很高。

exists 和 join如何选择

join

需要多张表进行连接,并且需要查询的字段不是来自一张表的,比如a.name,b.dept 这种情况需要使用join

exists

要查询的字段都在a表,但是有一个很复杂的条件,可以使用exists子句来描述后面复杂的查询条件

现实情况中,exists用的比较少,大家都想不起来用哈哈哈哈

and优先级高于or

比如一个查询,需要筛选名字为AAA,并且年龄为20或者21的数据,

sql语句如下:

select * from tab_a where name = 'AAA' and age = 20 or age = 21;

查询结果会变为

name = ‘AAA’ and age = 20的数据和

age=21的数据,查询结果错误。

需要改造sql语句如下:

select * from tab_a where name = 'AAA' and (age=20 or age=21)

尽量不要join超过三张表

单表索引控制在5个以内

索引越多,b+树越大,会影响插入、删除效率

组合索引的字段不能超过5个

key(a,b,c,d,e)不宜过多,由于最左匹配原则,如果查询的列在右边,那个查询的时候需要补充前几列的条件

并且,索引的长度过长会使b+树偏大,消耗存储空间

limit优化

limit语法如下:

从第一行开始返回,返回前n条数据

select * from tab_a order by a limit n

从第m行数据开始返回,返回后面的n条数据

select * from tab_a order by a limit m,n;

例如,如果要查询tab_a表的第3页,每页10条数据,可以如下进行:

select * from tab_a order by a limit 20,10;

limit相当于是一个指针,在遍历完前面的数据之后,找到需要的数据,再返回给用户,如果数据量非常大时,例如limit(25000,20),会扫描全表,limit效率会变得非常低,

这种情况的调优方式如下:

使用索引列子查询进行调优

调优前:

select film_id,description from film order by title limit 50,5

调优后:

explain select film.film_id,film.description from film inner join (select film_id from film order by title limit 1500,5) as lim using(film_id);

调优后,避免了limit指针扫描全表获取数据,而是先使用主键id进行查询,id在查询时,

只会使用b+树去访问到数据,不需要对整张表进行io,

速度更快,并且不需要回表,再将查询结果和主表做join,返回数据。

避免向数据库查询不必要的数据

数据库服务层会查询所有的结果,形成结果集,获取前面n条数据后关闭结果集,为了避免形成不必要的结果集,可以使用limit提升速率例如:

select * from tab_a where id = 'sdasafdf676d8' limit 1;

避免使用select *

如果需要不断的重复查询,使用redis进行缓存

尽量使用关联代替子查询

因为子查询在执行的过程中会将子查询结果放到临时表,增加了io,对内存的开销较大,而join可以利用join buffer进行快速匹配,运行速度较快。

group by, distinct, order by 时推荐使用索引列

使用自定义变量

什么是自定义变量?

set @one: = 1;
set @current_actor: = select actor_id from actor order by last_update desc limit 1 ;
set @last_week :=current_date-interval 1 week;
-- 使用如下
select count(1) from actor where last_update < @last_week;
select * from message where actor_id = @current_actor;

自定义变量使用场景:

优化排序

set @rownum:= 0;
select actor_id,@rownum:=@rownum+1 as rownum from actor limit 10;

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文