前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PostgreSQL技术大讲堂 - 第30讲:多表连接方式

PostgreSQL技术大讲堂 - 第30讲:多表连接方式

原创
作者头像
用户5892232
修改2023-09-22 15:18:50
2090
修改2023-09-22 15:18:50
举报
文章被收录于专栏:用户5892232的专栏

PostgreSQL从小白到专家,是从入门逐渐能力提升的一个系列教程,内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容,希望对热爱PG、学习PG的同学们有帮助,欢迎持续关注CUUG PG技术大讲堂。

第30讲:多表连接方式

内容1 : Nested Loop Join连接方式

内容2 : Merge Join连接方式

内容3 : Hash Join连接方式

多表连接方式

多表连接方式

三种连接方式:

nested loop join

merge join

hash join

支持所有join操作:

NATURAL INNER JOIN

INNER JOIN

LEFT/RIGHT OUTER JOIN

FULL OUTER JOIN

嵌套循环连接方式

Nested Loop Join

嵌套循环联接是最基本的联接操作,它可以用于任何联接条件。

Nested Loop Join图解

Materialized Nested Loop Join

我们使用下面的具体示例来探索执行器如何处理具体化嵌套循环连接的计划树,以及如何估计成本。

testdb=# EXPLAIN SELECT * FROM tbl_a AS a, tbl_b AS b WHERE a.id = b.id;

QUERY PLAN

-----------------------------------------------------------------------

Nested Loop (cost=0.00..750230.50 rows=5000 width=16)

Join Filter: (a.id = b.id)

-> Seq Scan on tbl_a a (cost=0.00..145.00 rows=10000 width=8)

-> Materialize (cost=0.00..98.00 rows=5000 width=8)

-> Seq Scan on tbl_b b (cost=0.00..73.00 rows=5000 width=8)

(5 rows)

Materialize成本估算

(Materialized) Nested Loop成本估算

Indexed Nested Loop Join

testdb=# EXPLAIN SELECT * FROM tbl_c AS c, tbl_b AS b WHERE c.id = b.id;

QUERY PLAN

--------------------------------------------------------------------------------

Nested Loop (cost=0.29..1935.50 rows=5000 width=16)

-> Seq Scan on tbl_b b (cost=0.00..73.00 rows=5000 width=8)

-> Index Scan using tbl_c_pkey on tbl_c c (cost=0.29..0.36 rows=1 width=8)

Index Cond:(id=b.id)

(4 rows)

具有外部索引扫描的嵌套循环联接的三种变体

Merge Join连接方式

Merge Join

Merge Join成本估算

testdb=# EXPLAIN SELECT * FROM tbl_a AS a, tbl_b AS b WHERE a.id = b.id AND b.id < 1000;

QUERY PLAN

-------------------------------------------------------------------------

Merge Join (cost=944.71..984.71 rows=1000 width=16)

Merge Cond: (a.id = b.id)

-> Sort (cost=809.39..834.39 rows=10000 width=8)

Sort Key: a.id

-> Seq Scan on tbl_a a (cost=0.00..145.00 rows=10000 width=8)

-> Sort (cost=135.33..137.83 rows=1000 width=8)

Sort Key: b.id

-> Seq Scan on tbl_b b (cost=0.00..85.50 rows=1000 width=8)

Filter: (id < 1000)

(9 rows)

Materialized Merge Join

Other Variations

强制使用merge join

testdb=# SET enable_hashjoin TO off;

testdb=# SET enable_nestloop TO off;

testdb=# EXPLAIN SELECT * FROM tbl_c AS c, tbl_b AS b WHERE c.id = b.id AND b.id < 1000;

QUERY PLAN

--------------------------------------------------------------------------------------

Merge Join (cost=135.61..322.11 rows=1000 width=16)

Merge Cond: (c.id = b.id)

-> Index Scan using tbl_c_pkey on tbl_c c (cost=0.29..318.29 rows=10000 width=8)

-> Sort (cost=135.33..137.83 rows=1000 width=8)

Sort Key: b.id

-> Seq Scan on tbl_b b (cost=0.00..85.50 rows=1000 width=8)

Filter: (id < 1000)

(7 rows)

materialized merge join with outer index scan

testdb=# SET enable_hashjoin TO off;

testdb=# SET enable_nestloop TO off;

testdb=# EXPLAIN SELECT * FROM tbl_c AS c, tbl_b AS b WHERE c.id = b.id AND b.id < 4500;

QUERY PLAN

--------------------------------------------------------------------------------------

Merge Join (cost=421.84..672.09 rows=4500 width=16)

Merge Cond: (c.id = b.id)

-> Index Scan using tbl_c_pkey on tbl_c c (cost=0.29..318.29 rows=10000 width=8)

-> Materialize (cost=421.55..444.05 rows=4500 width=8)

-> Sort (cost=421.55..432.80 rows=4500 width=8)

Sort Key: b.id

-> Seq Scan on tbl_b b (cost=0.00..85.50 rows=4500 width=8)

Filter: (id < 4500)

(8 rows)

indexed merge join with outer index scan

testdb=# SET enable_hashjoin TO off;

testdb=# SET enable_nestloop TO off;

testdb=# EXPLAIN SELECT * FROM tbl_c AS c, tbl_d AS d WHERE c.id = d.id AND d.id < 1000;

QUERY PLAN

--------------------------------------------------------------------------------------

Merge Join (cost=0.57..226.07 rows=1000 width=16)

Merge Cond: (c.id = d.id)

-> Index Scan using tbl_c_pkey on tbl_c c (cost=0.29..318.29 rows=10000 width=8)

-> Index Scan using tbl_d_pkey on tbl_d d (cost=0.28..41.78 rows=1000 width=8)

Index Cond: (id < 1000)

(5 rows)

Hash Join连接方式

Hash Join

In-Memory Hash Join

构建阶段:

将内部表的所有元组插入到一个批处理中

探测阶段:

将外部表的每个元组与批处理中的内部元组进行比较,如果满足连接条件,则进行连接

Hash Join

计划器处理转变

预处理

1、计划和转换CTE(如果查询中带有with列表,则计划器通过SS_process_ctes()函数处理每个with查询)

2、向上拉子查询

根据子查询的特点,改为自然连接查询。

testdb=# SELECT * FROM tbl_a AS a, (SELECT * FROM tbl_b) as b WHERE a.id = b.id;

testdb=# SELECT * FROM tbl_a AS a, tbl_b as b WHERE a.id = b.id;

3、将外部联接转换为内部联接

优化器可用规则

Getting the Cheapest Path

1、表数量小于12张,应用动态规划得到最优的计划

2、表数量大于12张,应用遗传查询优化器

参数 geqo_threshold指定的阈值(默认值为12)

3、分为不同的级别层次来处理

多表查询连接顺序选择

SGetting the Cheapest Path of a Triple-Table Query

testdb=# SELECT * FROM tbl_a AS a, tbl_b AS b, tbl_c AS c

testdb=# WHERE a.id = b.id AND b.id = c.id AND a.data < 40;

考虑3种组合:

{tbl_a,tbl_b,tbl_c}=min({tbl_a,{tbl_b,tbl_c}},{tbl_b,{tbl_a,tbl_c}},{tbl_c,{tbl_a,tbl_b}}).

创建多表查询的计划树· 此查询的EXPLAIN命令的结果如下所示

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档