Sql-Server

為什麼優化器在這裡選擇嵌套循環而不是合併連接?

  • November 30, 2019

我有 3 張桌子。#a是主要的一個和兩個輔助表,#b並且#c.

create table #a (a int not null, primary key (a asc)) ;
create table #b (b int not null, primary key (b asc)) ;
create table #c (c int not null, primary key (c asc)) ;

insert into #a (a)
select x*10 + y
from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))x(x)
cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))y(y) ;

insert into #b (b)
select a from #a where a % 5 > 0 ;

insert into #c (c)
select a from #a where a % 4 > 0 ;

如果我#a只用一個輔助表連接主表,查詢計劃中就會有 Merge Join。

select *
from #a a
inner join #b b on a = b ;

在此處輸入圖像描述

但是,如果我將主表#a與兩個輔助表一起加入,則將只有嵌套循環。

select *
from #a a
inner join #b b on a = b
inner join #c c on a = c ;

在此處輸入圖像描述

為什麼它會這樣工作,我應該怎麼做才能獲得兩個合併連接?

inner merge join提示。

為什麼它會這樣工作,我應該怎麼做才能獲得兩個合併連接?

通過三個表引用(最低要求),查詢符合基於成本的優化的事務處理(又名搜尋 0)階段。

此階段針對 OLTP 查詢,這些查詢通常受益於導航(基於索引)策略。嵌套循環連接是可用的主要物理連接類型(只有在此階段找不到有效的嵌套循環計劃時才考慮散列和合併)。

如果這個階段找到了一個低成本(足夠好)的計劃,那麼基於成本的優化就到此為止了。這可以防止在優化上花費更多時間,我們可以期望節省到目前為止找到的最佳解決方案。如果成本超過門檻值,優化器將進入快速計劃(搜尋 1)、並行快速計劃完全優化(搜尋 2)階段。

具有兩個表引用的查詢不符合事務處理的條件,並直接進入Q​​uick Plan,其中 Merge 和 Hash 連接可用。

有關更多資訊,請參閱我的Query Optimizer Deep Dive系列。

inner merge join提示。

如果您絕對必須提示物理連接類型,強烈推薦OPTION (MERGE JOIN). 這允許優化器仍然考慮更改連接順序。

加入提示,例如INNER MERGE JOIN帶有隱含的OPTION (FORCE ORDER),這嚴重限制了優化器的自由度,其後果是大多數人(包括專家)不理解的。

引用自:https://dba.stackexchange.com/questions/188448