MySQL优化——会导致全表扫描的情况以及解决方案

(1)like模糊查询

对于like ‘%...%’(全模糊)、左模糊like‘%...’。这样的条件,无法使用索引

解决办法:尽量不用模糊查询,可以用右模糊,可以走索引,即like ‘…%’

(2)询条件中is null、is not null 

应尽量避免在where 子句中对字段进行null 值判断,会走全表:

select id from t where num is null

解决办法:对于is null,可以建立组合索引,nvl(字段,0),对表和索引analyse后,is null查询时可以重新启用索引查找,但是效率还不是值得肯定;is not null 时永远不会使用索引

(3)查询条件中使用了不等于操作符(<>、!=)

解决方法:通过把不等于操作符改成or,可以使用索引

(4)组合索引使用不当

查询条件中没有前导列,导致索引不起作用,如没有job前导列:

create index skip1 on emp5(job,empno); 
select count(*) from emp5 where empno=7900; //全表扫描

 使用组合索引时,在排序时应按照组合索引中各列顺序进行排序(即使只有一个列需要排序),否则性能较差:

create index skip1 on emp5(job,empno,date); 
select job,empno from emp5 where job=’manager’and empno=’10’ ORDER BY date desc; //性能较差
select job,empno from emp5 where job=’manager’and empno=’10’ ORDER BY job,empno,date desc; //使用组合索引

(5)OR语句连接的条件中包含的列(左右)没有全部建立索引

例如:where子句中比较的两个条件,一个有索引,一个没索引,使用or则会引起全表扫描。例如:where A=1 or B=2,A上有索引,B上没索引,则比较B=2时会重新开始全表扫描

where条件下OR的改造:

如:select id from t where num=10 or num=20;

改造为:select id from t where num=10 union all select id from t where num=20;

(6)in 和not in 导致全表

 如:select id from t where num in(1,2,3);

(等效于select * from user where userId = 1 or userId = 2 or userId = 3;)

改造1:对于连续的数值,能用between 就不要用in :select id from t where num between 1 and 3;

改造2:用exists代替in:

(in查询的子条件返回结果必须只有一个字段,例如:select * from user where userId in (select id from B);

而不能是:select * from user where userId in (select id, age from B);   而exists就没有这个限制)

(7)在where字句对字段进行表达式或者函数操作

如:

select id from t where substring(name,1,3)='abc'; --name
select id from t where datediff(day,createdate,'2005-11-30')=0;  --‘2005-11-30’

改造为:

select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

 

 

  上一篇:explain的使用

若对你有帮助,欢迎关注!!点赞!!评论!!

你可能感兴趣的:(MySQL)