Gri*_*rim 5 join sql-server optimization database-internals
我有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 ;
Run Code Online (Sandbox Code Playgroud)
如果我只将主表#a
与一个辅助表连接,则查询计划中将有合并连接。
select *
from #a a
inner join #b b on a = b ;
Run Code Online (Sandbox Code Playgroud)
但是,如果我将主表#a
与两个辅助表连接起来,则只会有嵌套循环。
select *
from #a a
inner join #b b on a = b
inner join #c c on a = c ;
Run Code Online (Sandbox Code Playgroud)
为什么它会这样工作,我应该怎么做才能获得两个合并连接?
没有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)
,这严重限制了优化器的自由,其后果大多数人(包括专家)不理解。
归档时间: |
|
查看次数: |
5191 次 |
最近记录: |