前言
在pg_hint_plan技术内幕–02 Scan method中我们介绍了scan method的原理,本文我们继续深入探究Join method的原理。
目前支持的join method list如下:
Join method | NestLoop(table table[ table…]) | Forces nested loop for the joins on the tables specified. |
---|---|---|
HashJoin(table table[ table…]) | Forces hash join for the joins on the tables specified. | |
MergeJoin(table table[ table…]) | Forces merge join for the joins on the tables specified. | |
NoNestLoop(table table[ table…]) | Forces to not do nested loop for the joins on the tables specified. | |
NoHashJoin(table table[ table…]) | Forces to not do hash join for the joins on the tables specified. | |
NoMergeJoin(table table[ table…]) | Forces to not do merge join for the joins on the tables specified. |
主要是对NestLoop HashJoin MergeJoin三种join方式的控制。
原理
以MergeJoin(table table[ table…])为例:
在make_rel_from_joinlist时进入hook, set_join_config_options将hint指定的enable_mergejoin 置为on,并将其他scan method的startup_cost配置为disable_cost(即set NestLoop to off,set HashJoin to off) ,生成Mergejoin和Nestloop的joinpath, 最终计算最小代价确定joinpath为MergeJoin。
如图,sql默认走NestLoop,我们使用hint /*+ MergeJoin (du pu) */后走了MergeJoin。
debug关键过程做下验证:
首先set_join_config_options中:
enforce_mask=2 即set merge_join to on,set enable_nestloop to off,set enable_hashjoin to off
即Nestloop和Hashjoin的startup_cost为disable_cost
add_paths_to_joinrel :
mergejoin_allow总为true,为joinrel设置MergeJoin和Nestloop的path
enable_hashjoin为false,不涉及Hashjoin的path
由于Nestloop的startup_cost被设置为disable_cost,因此set_cheapest(rel)为T_MergePath
小结
本文深入分析了Join method的原理,其实就是对hint指定的几个表,将hint之外的join方式的startup_cost配置为disable_cost,这样最小代价就是hint指定的join方式了。