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;
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。