Sql-Server
為什麼優化器在這裡選擇嵌套循環而不是合併連接?
我有 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)階段。
具有兩個表引用的查詢不符合事務處理的條件,並直接進入Quick Plan,其中 Merge 和 Hash 連接可用。
有關更多資訊,請參閱我的Query Optimizer Deep Dive系列。
無
inner merge join
提示。如果您絕對必須提示物理連接類型,強烈推薦
OPTION (MERGE JOIN)
. 這允許優化器仍然考慮更改連接順序。加入提示,例如
INNER MERGE JOIN
帶有隱含的OPTION (FORCE ORDER)
,這嚴重限制了優化器的自由度,其後果是大多數人(包括專家)不理解的。