SQL Server執行計划那些事兒(1)——哈希、合並、嵌套聯接的選擇


接下來的文章是記錄自己曾經的盲點,同時也透漏了自己的發展歷程(可能發展也算不上,只能說是瞎混)。當然,一些盲點也在工作和探究過程中慢慢有些眉目,現在也願意發揚博客園的奉獻精神,拿出來和大家分享一下。

開門見山,直接入題

在進行Join的時候,數據庫優化器是怎么進行聯接呢?下面我們也詳細的講述。

在SQL Server中,有3中Join的策略——哈希匹配(Hash)、合並(Merge)、嵌套循環(Nested Loop).

在理解者三種聯接策略之前,我們先來簡單了解下哈希匹配聯接、合並聯接、嵌套循環聯接,

哈希匹配聯接:這種聯接有兩種輸入,即建立輸入和探測輸入。首先SQL Server會根據統計信息從兩張表中篩選出較小的表作為建立輸入,並且讀入所有行,然后在內存中根據關聯條件建立一個哈希表。在整個建立階段完成之后就進入探測階段。以后一行一行的對探測輸入進行掃描和計算,並為每個探測行計算哈希值,然后進行匹配(當然這里也分多種情況,建立輸入大於可用內存時等其他情況)。

合並聯接:合並連接要求兩個輸入都要在合並列上排序。由於每個輸入都已排序,因此Merge Join運算符將從每個輸入中獲取一行進行比較,如果行相等則進行返回,不等則舍棄。當數據量不大的時候,這種聯接方式比哈希匹配更加有效。

嵌套循環聯接:嵌套循環也稱“嵌套迭代”,他將一個聯接輸入用作外部輸入表,將另一個聯接輸入用作內部輸入表。外部循環逐行處理外部輸入表。內部循環逐行處理外部輸入表,內部循環會針對每個外部行執行,在內部輸入表中搜索匹配的行。

通過上面的介紹,我們也能分析出來(可以根據時間復雜度,和空間復雜度),以上三種聯接並沒有絕對的優劣。

大致可以分一下幾種情況:

(1)當數據量容量很大,且未排序的情況下,哈希匹配要優於其他兩種。

(2)當屬數據已經排序,且數據量不大的之后,合並連接更加有效。

(3)當結果集比較小,且數據容量不大的時候嵌套循環比較合適。

下面我們可以通過測試來查看SQL Server優化器的選擇。

我們先創建兩張表(Headers和Details):

1.執行下面查詢,查看執行計划:

select *

from Headers

inner join Details on Headers.ID=Details.HeaderID

go

2.查看執行計划,可以看出查詢優化器使用了哈希匹配:

3.在兩表中創建聚集索引

create nonclustered index index_details_headerID on details(headerID)

create unique clustered index index_details_ID_headerID on details(headerID,ID)

4、執行上面查詢,開啟執行計划,可以看出此時優化器使用了合並聯接

5.現在執行下面查詢語句(帶where 過濾):

select *from Headers inner join Details on Headers.ID=Details.HeaderID where Details.ID=500

6.通過查看執行計划得出,當結果集比較小的時候優化器選擇了嵌套循環:

 

總結

通過上面的我們可以得出,三種聯接各有優略,視乎情況而定。但是如果可以的話,應該在關聯列上建立索引。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM