mysql - 對(duì)于這兩句sql,一個(gè)是用or,一個(gè)是用union all,性能應(yīng)該是后面的好吧?
問(wèn)題描述
explain select * from ecs_ad where ad_id =1 or ad_id = 3;+----+-------------+--------+-------+---------------+---------+---------+------+------+-----------------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+--------+-------+---------------+---------+---------+------+------+-----------------------+| 1 | SIMPLE | ecs_ad | range | PRIMARY | PRIMARY | 2 | NULL | 2 | Using index condition |+----+-------------+--------+-------+---------------+---------+---------+------+------+-----------------------+1 row in set
這是union all的
explain select * from ecs_ad where ad_id = 4 union all select * from ecs_ad where ad_id = 3;+------+--------------+------------+-------+---------------+---------+---------+-------+------+-----------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+------+--------------+------------+-------+---------------+---------+---------+-------+------+-----------------+| 1 | PRIMARY | ecs_ad | const | PRIMARY | PRIMARY | 2 | const | 1 | NULL || 2 | UNION| ecs_ad | const | PRIMARY | PRIMARY | 2 | const | 1 | NULL || NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | Using temporary |+------+--------------+------------+-------+---------------+---------+---------+-------+------+-----------------+3 rows in set
問(wèn)題解答
回答1:首先,這兩個(gè)查詢性能差距應(yīng)該不大。因?yàn)?ad_id 列是主鍵.
根據(jù) type 列分析:or 查詢,type:rangeunion all 查詢:type:const / const / ALL
首先可以確認(rèn)的是,const 要優(yōu)于 range.const 也是因?yàn)?ad_id 為主鍵.
但是 union all 做了三次操作,兩次主鍵或者唯一索引查詢 type:const,但最后組合到一起時(shí) type:ALLtype:ALL 本身性能比 range 還要差
從 Type 看,or 查詢性能應(yīng)該更好.
Extra 分析or 查詢:Using index conditionunion all 查詢:NULL / NULL / Using temporary
Using index condition 為 MySQL 5.6 版本以后新添加的特性,索引條件推送。
首先說(shuō)一下沒(méi)有索引條件推送時(shí)候的處理流程:
優(yōu)化器沒(méi)有使用ICP時(shí),數(shù)據(jù)訪問(wèn)和提取的過(guò)程如下:
1) 當(dāng)storage engine讀取下一行時(shí),首先讀取索引元組(index tuple),然后使用索引元組在基表中(base table)定位和讀取整行數(shù)據(jù)。2) sever層評(píng)估where條件,如果該行數(shù)據(jù)滿足where條件則使用,否則丟棄。3) 執(zhí)行1),直到最后一行數(shù)據(jù)。
當(dāng)存在索引條件推送時(shí)候的處理流程:
優(yōu)化器使用ICP時(shí),server層將會(huì)把能夠通過(guò)使用索引進(jìn)行評(píng)估的where條件下推到storage engine層。數(shù)據(jù)訪問(wèn)和提取過(guò)程如下:
1) storage engine從索引中讀取下一條索引元組。2) storage engine使用索引元組評(píng)估下推的索引條件。如果沒(méi)有滿足wehere條件,storage engine將會(huì)處理下一條索引元組(回到上一步)。只有當(dāng)索引元組滿足下推的索引條件的時(shí)候,才會(huì)繼續(xù)去基表中讀取數(shù)據(jù)。3) 如果滿足下推的索引條件,storage engine通過(guò)索引元組定位基表的行和讀取整行數(shù)據(jù)并返回給server層。4) server層評(píng)估沒(méi)有被下推到storage engine層的where條件,如果該行數(shù)據(jù)滿足where條件則使用,否則丟棄。
簡(jiǎn)單來(lái)說(shuō),沒(méi)有 ICP 時(shí),存儲(chǔ)引擎返回所有滿足條件的整行數(shù)據(jù),在 service 層進(jìn)行 where 條件過(guò)濾。有 ICP 時(shí),where 條件下推到存儲(chǔ)引擎層,存儲(chǔ)引擎直接返回滿足條件的數(shù)據(jù)。性能自然提高很多。
對(duì)于 ICP 的相關(guān)介紹,可以查看這里
而 Using temporary 表示隱式臨時(shí)表,意思是 MySQL 會(huì)在產(chǎn)生一個(gè)臨時(shí)表,存放中間數(shù)據(jù)。因?yàn)?union all 是分開(kāi)處理,最后合并的關(guān)系。從 Extra 看,也應(yīng)該是 or 查詢性能更高。
綜合來(lái)看:OR 查詢的性能應(yīng)該有優(yōu)于 UNION ALL .
由于所有查詢性能都隨著數(shù)據(jù)量增大而變化,以上分析只是單看題主所貼的 Explain 分析結(jié)果。也并不是說(shuō) OR 在所有情況下都優(yōu)于 UNION ALL。
以上為個(gè)人意見(jiàn),如有錯(cuò)誤,請(qǐng)指正。
回答2:這兩個(gè)語(yǔ)句,無(wú)區(qū)別。一般or連接兩個(gè)不同字段,無(wú)法使用索引的時(shí)候,性能會(huì)比較差,不如union,可以嘗試修改。
