最近看书《高性能MySql》,5.3.3 节中介绍在MySql 5.0和更新的版本中,`select name , hobby from user where name=1 or hobby = 1;` 这个语句如果 name 和 user 都建立了单独的索引,查询能够同时使用着两个单列索引,并将结果合并。 explain sql 的结果中type 为index_merge。
下面,目前我发现这个并不会像书中描述的那样。
第一张图是数据库的版本,8.0.13,数据库引擎 InnoDB
在最后explain 语句中,可以看到type =all,所以即使创建了两个单列索引,依然是全表扫描。
下面我将展示优化流程。
1. 使用union ,
使用union,union 会自动做数据去重,但是在此过程中会建立临时表,最后返回的是临时表的合并的结果,在最后一次查询中也是一个全表扫描
2. 使用union all
使用union all, union all 是直接合并数据集,并不会做去重操作,减少了一次合并操作,可以看到其中并没有涉及到临时表
经过以上实验,可以看出mysql 在遇到or的多列查询时,即使每一列都建立了单独索引,也并不会自动优化SQL。所以建议不要使用or,避免全表扫描。而使用union时,由于数据库需要帮忙进行数据去重,其实是会进行3次数据操作,远比不上使用union all 时,只会进行两次数据操作。
结论:进行多个条件并集查询时,不要使用or, 不要寄希望于数据库的优化,而应该使用union all 或in 等语句优化SQL