搜尋

首頁  >  問答  >  主體

mysql - 對於這兩句sql,一個是用or,一個是用union all,效能應該是後面的好吧?

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
PHPzPHPz2747 天前1162

全部回覆(2)我來回復

  • PHPz

    PHPz2017-05-18 10:58:52

    首先,這兩個查詢效能差距應該不大。
    因為 ad_id 欄位是主鍵.

    根據 type 欄位分析:
    or 查詢,type:rangetype:range
    union all 查询:type:const / const / ALLunion all 查詢:type:const / const / ALL

    首先可以確認的是,const 要優於 range.const 要优于 range.
    constconst 也是因為 ad_id 為主鍵.

    但是 union all 做了三次操作,兩次主鍵或唯一索引查詢 type:const,但最後組合到一起時 type:ALL
    type:ALL 本身性能比 range 還要差

    從 Type 看,or 查詢效能應該更好.

    Extra 分析
    or 查詢:Using index conditionUsing index condition
    union all 查询:NULL / NULL / Using temporaryunion all 查詢:NULL / NULL / Using temporary

    Using index condition 為 MySQL 5.6 版本以後新加入的特性,索引條件推送。

    先說一下沒有索引條件推送時候的處理流程:

    優化器沒有使用ICP時,資料存取與擷取的過程如下:

    1) 當storage engine讀取下一行時,先讀取索引元組(index tuple),然後使用索引元組在基底表中(base table)定位和讀取整行資料。
    2) sever層評估where條件,如果該行資料滿足where條件則使用,否則丟棄。
    3) 執行1),直到最後一行資料。

    當存在索引條件推播時候的處理流程:

    優化器使用ICP時,server層將會把能夠透過使用索引進行評估的where條件下推到storage engine層。資料存取和提取過程如下:

    1) storage engine從索引中讀取下一條索引元組。
    2) storage engine使用索引元組評估下推的索引條件。如果沒有滿足wehere條件,storage engine將會處理下一個索引元組(回到上一個步驟)。只有當索引元組滿足下推的索引條件的時候,才會繼續去基底表中讀取資料。
    3) 如果滿足下推的索引條件,storage engine透過索引元組定位基底表的行和讀取整行資料並傳回server層。
    4) server層評估沒有被下推到storage engine層的where條件,如果該行資料滿足where條件則使用,否則丟棄。

    簡單來說,沒有 ICP 時,儲存引擎會傳回所有滿足條件的整行數據,在 service 層進行 where 條件過濾。
    有 ICP 時,where 條件下推到儲存引擎層,儲存引擎直接傳回符合條件的資料。
    性能自然提高很多。

    對於 ICP 的相關介紹,可以查看這裡

    而 Using temporary 表示隱式臨時表,意思是 MySQL 會在產生一個臨時表,存放中間資料。因為 union all 是分開處理,最後合併的關係。
    從 Extra 看,也應該是 or 查詢效能更高。

    綜合來看:OR 查詢的效能應該有優於 UNION ALL .

    由於所有查詢效能都隨著資料量增加而變化,以上分析只是單看題主所貼的 Explain 分析結果。也並不是說 OR 在所有情況下都優於 UNION ALL。

    以上為個人意見,如有錯誤,請指正。

    回覆
    0
  • 黄舟

    黄舟2017-05-18 10:58:52

    這兩個語句,無差別。
    一般or連接兩個不同字段,無法使用索引的時候,效能會比較差,不如union,可以嘗試修改。

    回覆
    0
  • 取消回覆