天天看點

MySQL 子查詢優化[IN/EXISTS]--smei join

MySQL 裡面有哪些子查詢呢?

标量子查詢

内聯視圖

半連接配接/反連接配接

本篇主要講解半連接配接查詢

半連接配接?可以這麼了解 where 條件後面有In/EXISTS這樣的子查詢稱為semi jion

格式:select ..... from outer_tables where expr in (select .... from inner_tables ...) and ...

為什麼要用semi join來進行優化子查詢?

因為where後面的子查詢每掃描一條資料,Where子查詢都會被重新執行一遍,這樣效率就會很低如果父表資料很多帶來什麼問題?那麼就有了将子查詢的結果提升到FROM中,不需要再父表中每個符合條件的資料都要去把子查詢執行一輪了。

MySQL又是需要滿足什麼條件才會轉換成semi jion?

子查詢是in or = any , 不可以是not in

子查詢隻能包含一個Query bolock, 不可以有union等操作

子查詢不能包含group by 或者having

不能包含聚合函數

子查詢的謂詞是where子句的一部分

子查詢謂詞不可以是外部查詢條件或者否定查詢條件

不可以包含Straight_join 限定詞

隻能用于select insert,而update,delete則都不可用

有哪些因為可以将半連接配接和正常連接配接進行區分?

在semi-join 中内部表不會在結果中造成重複

内部table中沒有列添加到操作結果中。

這意味着半連接配接的結果是外表行中的子集。這也意味着大部分的半連接配接的特殊處理是關于内部表中有效的消除重複

那麼我們了解了為什麼有semi jion,滿足什麼條件轉換成semi join以及如何區分,那對于semi jion 又有哪些優化政策呢?

--因為半連接配接是一種正常連接配接操作,并結合從半連接配接内部表中删除可能的重複項。

MySQL實作了四種不同的半連接配接執行政策,它們有不同的删除重複項的方法:

FirstMatch

DuplicateWeedout

Materialization

LooseScan

FirstMatch:

當掃描inner table 來組合資料時,并且有多個符合條件的資料時,隻選擇第一條滿足條件的記錄,連接配接後的結果,存與臨時表。

EG:

MySQL 子查詢優化[IN/EXISTS]--smei join

由于Germany有兩個大城市(在該圖中),它将被放入查詢輸出兩次。 這是不正确的,SELECT ... FROM Country不應該産生兩次相同的國家記錄。 FirstMatch政策避免了一旦找到第一次真正的比對就通過快速執行生成重複項:

MySQL 子查詢優化[IN/EXISTS]--smei join

如果沒有開啟simi jion 的方式下運作:

DuplicateWeedout :

先和子查詢做簡單的inner join 操作,并使用臨時表(建有Primary key)來消除重複記錄。

首先做inner join 操作:

MySQL 子查詢優化[IN/EXISTS]--smei join

内部連接配接産生重複項。 Germany有三次big city,此時将DuplicateWeedout政策進行應用:

MySQL 子查詢優化[IN/EXISTS]--smei join

該查詢将讀取City表中的237行,并且它們中的每個都将在Country表中進行主鍵查找,進而得到另外237行。 這總共提供了474行,并且您需要在臨時表中添加237個查找。

那麼關閉semi join:

這個執行計劃将會讀取到(239+239 * 18)=4541行資料,這個會比較慢。

--另外兩種政策下次分享

圖檔來源MariaDB官網

繼續閱讀