最近看書《高性能MySql》,5.3.3 節(jié)中介紹在MySql 5.0和更新的版本中萌狂,`select name , hobby from user where name=1 or? hobby = 1;` 這個語句如果 name 和 user 都建立了單獨的索引宵蛀,查詢能夠同時使用著兩個單列索引褪测,并將結(jié)果合并滞磺。 explain sql 的結(jié)果中type 為index_merge。
下面意述,目前我發(fā)現(xiàn)這個并不會像書中描述的那樣。
第一張圖是數(shù)據(jù)庫的版本吮蛹,8.0.13,數(shù)據(jù)庫引擎 InnoDB
在最后explain 語句中荤崇,可以看到type =all,所以即使創(chuàng)建了兩個單列索引潮针,依然是全表掃描术荤。
下面我將展示優(yōu)化流程。
1. 使用union 每篷,
使用union瓣戚,union 會自動做數(shù)據(jù)去重,但是在此過程中會建立臨時表焦读,最后返回的是臨時表的合并的結(jié)果子库,在最后一次查詢中也是一個全表掃描? ??
2. 使用union all
使用union all, union all 是直接合并數(shù)據(jù)集,并不會做去重操作矗晃,減少了一次合并操作仑嗅,可以看到其中并沒有涉及到臨時表
經(jīng)過以上實驗,可以看出mysql 在遇到or的多列查詢時喧兄,即使每一列都建立了單獨索引无畔,也并不會自動優(yōu)化SQL。所以建議不要使用or吠冤,避免全表掃描浑彰。而使用union時,由于數(shù)據(jù)庫需要幫忙進行數(shù)據(jù)去重拯辙,其實是會進行3次數(shù)據(jù)操作郭变,遠比不上使用union all 時颜价,只會進行兩次數(shù)據(jù)操作。
結(jié)論:進行多個條件并集查詢時诉濒,不要使用or, 不要寄希望于數(shù)據(jù)庫的優(yōu)化周伦,而應(yīng)該使用union all 或in 等語句優(yōu)化SQL