⑤ using where
表示需要【回表查询】,表示既在索引中进行了查询,又回到了源表进行了查询。
# 删除test02中的复合索引idx_a1_a2 drop index idx_a1_a2 on test02; # 将a1字段,新增为一个索引 create index a1_index on test02(a1); # 查看执行计划 explain select a1,a3 from test02 where a1="" and a3="" ;
结果如下:
结果分析:我们使用了索引a1,表示我们使用了索引进行查询。但是又对于a3字段,我们并没有使用索引,因此对于a3字段,需要回源表查询,这个时候出现了using where。
⑥ impossible where(了解)
当where子句永远为False的时候,会出现impossible where。
# 查看执行计划 explain select a1 from test02 where a1="a" and a1="b" ;
结果如下:
6、优化示例
1)引入案例
# 创建新表 create table test03 ( a1 int(4) not null, a2 int(4) not null, a3 int(4) not null, a4 int(4) not null ); # 创建一个复合索引 create index a1_a2_a3_test03 on test03(a1,a2,a3); # 查看执行计划 explain select a3 from test03 where a1=1 and a2=2 and a3=3;
结果如下:
【推荐写法】:复合索引顺序和使用顺序一致。
【不推荐写法】:复合索引顺序和使用顺序不一致。
# 查看执行计划 explain select a3 from test03 where a3=1 and a2=2 and a1=3;
结果如下:
结果分析:虽然结果和上述结果一致,但是不推荐这样写。但是这样写怎么又没有问题呢?这是由于SQL优化器的功劳,它帮我们调整了顺序。
最后再补充一点:对于复合索引,不要跨列使用。
# 查看执行计划 explain select a3 from test03 where a1=1 and a3=2 group by a3;
结果如下:
结果分析:a1_a2_a3是一个复合索引,我们使用a1索引后,直接跨列使用了a3,直接跳过索引a2,因此索引a3失效了。当再使用a3进行分组的时候,就会出现using where。
2)单表优化
# 创建新表 create table book ( bid int(4) primary key, name varchar(20) not null, authorid int(4) not null, publicid int(4) not null, typeid int(4) not null ); # 插入数据 insert into book values(1,'tjava',1,1,2) ; insert into book values(2,'tc',2,1,2) ; insert into book values(3,'wx',3,2,1) ; insert into book values(4,'math',4,2,3) ;
结果如下:
案例:查询authorid=1且typeid为2或3的bid,并根据typeid降序排列。
explain select bid from book where typeid in(2,3) and authorid=1 order by typeid desc ;
结果如下:
这是没有进行任何优化的SQL,可以看到typ为ALL类型,extra为using filesort,可以想象这个SQL有多恐怖。
优化:添加索引的时候,要根据MySQL解析顺序添加索引,又回到了MySQL的解析顺序,下面我们再来看看MySQL的解析顺序。
from .. on.. join ..where ..group by ..having ..select dinstinct ..order by ..limit ..
① 优化1:基于此,我们进行索引的添加,并再次查看执行计划。
# 添加索引 create index typeid_authorid_bid on book(typeid,authorid,bid); # 再次查看执行计划 explain select bid from book where typeid in(2,3) and authorid=1 order by typeid desc ;
结果如下:
结果分析:结果并不是和我们想象的一样,还是出现了using where,查看索引长度key_len=8,表示我们只使用了2个索引,有一个索引失效了。