PostgreSQL17优化SubPlan和InitPlan节点在EXPLAIN中显示内容
2025年第一篇博客,我们接着来看看PostgreSQL17在EXPLAIN输出方面的优化。我们这次看的是对于EXPLAIN输出中SubPlan和InitPlan节点的优化。总结起来就是两点:
- 去掉SubPlan和InitPlan节点的返回参数“$n”
- 对带SubPlan、hash SubPlan和InitPlan节点进行了补充
准备测试环境
在这里,我们先来创建测试表,可以不初始化数据。
create table test10(id integer primary key,name varchar(50),amount numeric(10,2),createdate timestamp without time zone);
复制
去掉SubPlan和InitPlan节点的返回参数“$n”
在PostgreSQL16.3查看执行计划
在这里我们先来看看在PostgreSQL16.3中explain中InitPlan和SubPlan节点的信息。
InitPlan节点
explain (costs off) select min(id) from test10; QUERY PLAN ----------------------------------------------------------- Result InitPlan 1 (returns $0) -> Limit -> Index Only Scan using test10_pkey on test10 Index Cond: (id IS NOT NULL) (5 rows) Time: 0.357 ms
复制
SubPlan节点
EXPLAIN (COSTS OFF) UPDATE test10 t SET (name,amount) = (SELECT s.name,s.amount FROM test10 s WHERE s.id = t.id) WHERE 1 = 2; QUERY PLAN -------------------------------------------------------- Update on test10 t -> Result One-Time Filter: false SubPlan 1 (returns $1,$2) -> Index Scan using test10_pkey on test10 s Index Cond: (id = t.id) (6 rows)
复制
从explain的输出可以看出,在InitPlan和SubPlan节点后面,都含有returns $1的信息,如果需要返回多个参数就是($1,n)。
在PostgreSQL17查看执行计划
我们再来看看在PostgreSQL17中explain中InitPlan和SubPlan节点的信息。
InitPlan节点
postgres=# explain (costs off) select min(id) from test10; QUERY PLAN ----------------------------------------------------------- Result InitPlan 1 -> Limit -> Index Only Scan using test10_pkey on test10 (4 rows)
复制
SubPlan节点
postgres-# SET (name,amount) = (SELECT s.name,s.amount FROM test10 s WHERE s.id = t.id) postgres-# WHERE 1 = 2; QUERY PLAN -------------------------------------------------------- Update on test10 t -> Result One-Time Filter: false SubPlan 1 -> Index Scan using test10_pkey on test10 s Index Cond: (id = t.id) (6 rows)
复制
从explain的输出可以看出,在PostgreSQL17中去掉了InitPlan和SubPlan节点后面的返回参数信息(returns $1)。
对含有SubPlan、hash SubPlan和InitPlan节点进行了补充
在PostgreSQL16.3查看执行计划
EXPLAIN (costs off) SELECT * FROM test10 WHERE createdate > (SELECT current_date) AND amount NOT IN (VALUES (1),(2)); QUERY PLAN ------------------------------------------------------------ Seq Scan on test10 Filter: ((createdate > $0) AND (NOT (hashed SubPlan 2))) InitPlan 1 (returns $0) -> Result SubPlan 2 -> Values Scan on "*VALUES*" (6 rows)
复制
在PostgreSQL17查看执行计划
EXPLAIN (costs off) SELECT * FROM test10 WHERE createdate > (SELECT current_date) AND amount NOT IN (VALUES (1),(2)); ------------------------------------------------------------------------------------------------------------ Seq Scan on test10 Filter: ((createdate > (InitPlan 1).col1) AND (NOT (ANY (amount = ((hashed SubPlan 2).col1)::numeric)))) InitPlan 1 -> Result SubPlan 2 -> Values Scan on "*VALUES*" (6 rows)
复制
针对含有SubPlan、hash SubPlan和InitPlan节点,去掉了EXPLAIN使用“$n”来表示subplan和initplan输出参数,而是使用(InitPlan n) . colx或(SubPlan n) . colx表示该子计划的第X个输出列,其中n为InitPlan或SubPlan节点的序号。另外就是条件显示得更清楚,从以前的NOT (hashed SubPlan 2)信息,使用NOT (ANY (amount = ((hashed SubPlan 2).col1)::numeric)所取代,现在它与查询中的条件相关联。
总结
我相信通过上面的实验,大概也可以清晰的知道,在PostgreSQL17版本中对于EXPLAIN输出中SubPlan和InitPlan节点查看比较详细的内容而且更加简洁明,对于我们查看执行计划还是有益的。
参考
https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=fd0398fcb
https://postgrespro.com/blog/pgsql/5971224#commit_fd0398fc
– / END / –
可以通过下面的方式联系我
如果这篇文章为你带来了灵感或启发,就请帮忙点赞、收藏、转发;如果文章中不严谨或者错漏之处,请及时评论指正。非常感谢!
评论
