IN與EXISTS的效能比較示例

2022-09-03 15:00:28 字數 2134 閱讀 6887

很多朋友對in與exists的使用存在疑問﹐為什麼in就比exists的效能差呢﹖

首先大家得了解如何使用查詢分析器檢視t-sql/sql的執行計畫,以及如何在sqlserver資料庫的幫助中檢視相關資訊。

圖一圖二

在執行圖一中後兩個sql語句前,必須開啟「顯示執行計畫」開關,按ctrl+k組合鍵,按f5執行後,返回同樣的記錄,查詢成本卻相去甚遠,為什麼呢?使用exists的查詢在執行計畫中使用了nested loops與left semi join等運算子;而使用in的查詢在執行中使用了hash match與right semi join運算子。

在sqlserver的聯機幫助中,輸入nested loop等可以看到它們的說明。

關於巢狀迴圈聯接

巢狀迴圈聯接也稱為巢狀迭代,它將乙個聯接輸入用作外部輸入表(顯示為圖形執行計畫中的頂端輸入),將另乙個聯接輸入用作內部(底端)輸入表。外部迴圈逐行消耗外部輸入表。內部迴圈為每個外部行執行,在內部輸入表中搜尋匹配行。最簡單的情況是,搜尋時掃瞄整個表或索引;這稱為單純巢狀迴圈聯接。如果搜尋時使用索引,則稱為索引巢狀迴圈聯接。如果將索引生成為查詢計畫的一部分(並在查詢完成後立即將索引破壞),則稱為臨時索引巢狀迴圈聯接。查詢優化器考慮所有這些不同形式。如果外部輸入很小而內部輸入很大且預先建立了索引,則巢狀迴圈聯接尤其有效。在許多小事務中(如那些只影響較小的一組行的事務),索引巢狀迴圈聯接遠比合併聯接和雜湊聯接優越。

但在大查詢中,巢狀迴圈聯接通常不是最佳選擇。

了解雜湊聯接

雜湊聯接有兩種輸入:生成輸入和探測輸入。查詢優化器指派這些角色,使兩個輸入中較小的那個作為生成輸入。

雜湊聯接可用於許多態別的集合匹配操作:內聯接,左向外聯接、右向外聯接和完整外聯接,左向半聯接和右向半聯接、交集、聯合和差分。而且,雜湊聯接的變化形式能夠進行重複項刪除和分組操作(如

sum(salary) group by department

)。這些修改對生成和探測角色只使用乙個輸入。

與合併聯接相似,只有當聯接謂詞中至少有乙個等效

(where)

子句時才能使用雜湊聯接。然而,聯接一般用於重組合由主鍵和外來鍵之間的等效謂詞表達的關係,因此大多數聯接至少有乙個等效子句。用等效謂詞表達的列集合稱為雜湊鍵,因為這些列有助於雜湊函式。還可以有附加的謂詞,並且可以將這些謂詞取值為駐留謂詞以與雜湊值比較分開。雜湊鍵可以是表示式,只要能從單個行中的列對其進行排它計算。在分組操作中,按列表分組的列是雜湊鍵。在交集等集合操作中以及刪除複製項時,雜湊鍵由所有列組成。

記憶體中的雜湊聯接

雜湊聯接先掃瞄或計算整個生成輸入,然後在記憶體中生成雜湊表。根據為雜湊鍵計算出的雜湊值,將每行插入雜湊儲存桶。如果整個生成輸入比可用記憶體少,則可以將所有行都插入雜湊表中。生成階段後接著是探測階段。一次一行地對整個探測輸入進行掃瞄或計算,並為每個探測行計算雜湊鍵的值,掃瞄相應的雜湊儲存桶並生成匹配項。

grace

雜湊聯接

如果生成輸入不適合記憶體,雜湊聯接將分步進行。每一步都包括生成階段和探測階段。首先,消耗整個生成和探測輸入並(使用雜湊鍵上的雜湊函式)將其分割槽為多個檔案。這類檔案的數目稱為分割槽輸出端。通過使用雜湊鍵上的雜湊函式,可以保證任意兩個聯接記錄必在相同的檔案對中。因此,聯接兩個大輸入的任務簡化為相同任務的多個較小的例項。然後將雜湊聯接應用於每對分割槽檔案。

遞迴雜湊聯接

如果生成輸入非常大,以至於標準外部合併排序的輸入需要多個合併級別,則需要多個分割槽步驟和多個分割槽級別。如果只有某些分割槽較大,則只需對這些分割槽使用附加的分割槽步驟。為使所有的分割槽步驟盡可能快,將使用大的非同步

i/o

操作以便單個執行緒就能使多個磁碟驅動器繁忙工作。

說明

如果生成輸入較大但並不比可用記憶體大很多,則記憶體中的雜湊聯接和

grace

雜湊聯接的元素將合併成乙個步驟,產生混合雜湊聯接。

在優化過程中並不總能確定使用什麼樣的雜湊聯接。因此,

microsoft® sql server™ 2000

開始時使用記憶體中的雜湊聯接,然後根據生成輸入的大小逐漸轉換到

grace

雜湊聯接和遞迴雜湊聯接。

如果優化器錯誤地預計兩個輸入中哪個較小並由此確定哪個作為生成輸入,生成角色和探測角色將動態逆轉。雜湊聯接確保使用較小的溢位檔案作為生成輸入。這一技術稱為角色逆轉。

mysql的exists 與 in 的效能比較

in 是把外表和內錶作hash 連線,而exists是對外表作loop迴圈,每次loop迴圈再對內表進行查詢。一直以來認為exists比in效率高的說法是不準確的。如果查詢的兩個表大小相當,那麼用in和exists差別不大。如果兩個表中乙個較小,乙個是大表,則子查詢表大的用exists,子查詢錶小的...

mysql的exists 與 in 的效能比較

in 是把外表和內錶作hash 連線,而exists是對外表作loop迴圈,每次loop迴圈再對內表進行查詢。一直以來認為exists比in效率高的說法是不準確的。如果查詢的兩個表大小相當,那麼用in和exists差別不大。如果兩個表中乙個較小,乙個是大表,則子查詢表大的用exists,子查詢錶小的...

mysql的exists 與 in 的效能比較

in 是把外表和內錶作hash 連線,而exists是對外表作loop迴圈,每次loop迴圈再對內表進行查詢。一直以來認為exists比in效率高的說法是不準確的。如果查詢的兩個表大小相當,那麼用in和exists差別不大。如果兩個表中乙個較小,乙個是大表,則子查詢表大的用exists,子查詢錶小的...