千家信息网

PostgreSQL新特性分析

发表于:2025-11-08 作者:千家信息网编辑
千家信息网最后更新 2025年11月08日,这篇文章主要介绍"PostgreSQL新特性分析",在日常操作中,相信很多人在PostgreSQL新特性分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Postgre
千家信息网最后更新 2025年11月08日PostgreSQL新特性分析

这篇文章主要介绍"PostgreSQL新特性分析",在日常操作中,相信很多人在PostgreSQL新特性分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"PostgreSQL新特性分析"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

在PG 8.4 ~ PG 11,PG会把WITH中的查询视为"optimization fence"(优化围栏,与WITH外的查询隔离,独立优化),也就意味着谓词下推等优化手段无法应用到WITH子句中,考虑到CTE在大多数情况下是为了增强可读性而存在,因此在PG 12中,满足以下三个条件的,优化器将不会对CTE"视而不见"而是执行"积极的"优化.
A.递归查询
B.没有任何副作用(side effect)
C.仅在查询的后续部分引用一次

谓词下推
测试脚本:

drop table  if exists t_w1;drop table  if exists t_w2;drop table  if exists t_w3;create table t_w1(id int ,c1 varchar(20));create table t_w2(id int ,c1 varchar(20));create table t_w3(id int ,c1 varchar(20));insert into t_w1 select x,x||'' from generate_series(1,10000) as x;insert into t_w2 select x/2,(x/2)||'' from generate_series(1,10000) as x;insert into t_w3 select x,x||'' from generate_series(1,10000) as x;

查询语句:

WITH t1 AS ( SELECT * FROM t_w1 WHERE t_w1.id % 4 = 0 ) SELECT * FROM t1   JOIN t_w2 as t2   ON t2.id = t1.id     AND t1.id < 100;

在PG 11中,其执行计划如下:

version                                                 -------------------------------------------------------------------------------------------- PostgreSQL 11.2 on x86_XX-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16), XX-bit(1 row)testdb=# explain analyze WITH t1 AS ( SELECT * FROM t_w1 WHERE t_w1.id % 4 = 0 ) testdb-# SELECT * FROM t1 testdb-#   JOIN t_w2 as t2 testdb-#   ON t2.id = t1.id testdb-#      AND t1.id < 100;                                                   QUERY PLAN                                                    -------------------------------------------------------------------------------------------- Hash Join  (cost=205.34..396.18 rows=34 width=70) (actual time=8.576..11.187 rows=48 loops=1)   Hash Cond: (t2.id = t1.id)   CTE t1     ->  Seq Scan on t_w1  (cost=0.00..204.00 rows=50 width=8) (actual time=0.029..6.074 rows=2500 loops=1)           Filter: ((id % 4) = 0)           Rows Removed by Filter: 7500   ->  Seq Scan on t_w2 t2  (cost=0.00..153.00 rows=10000 width=8) (actual time=0.030..1.166 rows=10000 loops=1)   ->  Hash  (cost=1.12..1.12 rows=17 width=62) (actual time=8.536..8.536 rows=24 loops=1)         Buckets: 1024  Batches: 1  Memory Usage: 9kB         ->  CTE Scan on t1  (cost=0.00..1.12 rows=17 width=62) (actual time=0.033..8.521 rows=24 loops=1)               Filter: (id < 100)               Rows Removed by Filter: 2476 Planning Time: 1.913 ms Execution Time: 11.357 ms(14 rows)

在PG 12中,其执行计划如下:

testdb=# select version();                                                  version                                                   -------------------------------------------------------------------------------------------- PostgreSQL 12beta1 on x86_XX-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16), XX-bit(1 row)testdb=# explain analyze WITH t1 AS ( SELECT * FROM t_w1 WHERE t_w1.id % 4 = 0 ) testdb-# SELECT * FROM t1 testdb-#   JOIN t_w2 as t2 testdb-#   ON t2.id = t1.id testdb-#      AND t1.id < 100;                                                   QUERY PLAN                                                    -------------------------------------------------------------------------------------------- Hash Join  (cost=229.01..419.52 rows=1 width=16) (actual time=6.974..17.156 rows=48 loops=1)   Hash Cond: (t2.id = t_w1.id)   ->  Seq Scan on t_w2 t2  (cost=0.00..153.00 rows=10000 width=8) (actual time=0.076..5.205 rows=10000 loops=1)   ->  Hash  (cost=229.00..229.00 rows=1 width=8) (actual time=6.882..6.882 rows=24 loops=1)         Buckets: 1024  Batches: 1  Memory Usage: 9kB         ->  Seq Scan on t_w1  (cost=0.00..229.00 rows=1 width=8) (actual time=0.077..6.842 rows=24 loops=1)               Filter: ((id < 100) AND ((id % 4) = 0))               Rows Removed by Filter: 9976 Planning Time: 1.677 ms Execution Time: 17.244 ms(10 rows)

可以看到,在PG 11中,谓词(id < 100)不会下推CTE中,但在PG 12中,优化器则把谓词下推到CTE中(Filter: ((id < 100) AND ((id % 4) = 0))).

New Option
如果希望12的优化器行为与先前的一样,则加入Option : MATERIALIZED.

testdb=# explain analyze WITH t1 AS MATERIALIZED( SELECT * FROM t_w1 WHERE t_w1.id % 4 = 0 ) SELECT * FROM t1   JOIN t_w2 as t2   ON t2.id = t1.id      AND t1.id < 100;                                                   QUERY PLAN                                                    ------------------------------------------------------------------------------------------- Hash Join  (cost=205.34..396.18 rows=34 width=70) (actual time=30.705..48.549 rows=48 loops=1)   Hash Cond: (t2.id = t1.id)   CTE t1     ->  Seq Scan on t_w1  (cost=0.00..204.00 rows=50 width=8) (actual time=0.152..21.274 rows=2500 loops=1)           Filter: ((id % 4) = 0)           Rows Removed by Filter: 7500   ->  Seq Scan on t_w2 t2  (cost=0.00..153.00 rows=10000 width=8) (actual time=0.154..8.582 rows=10000 loops=1)   ->  Hash  (cost=1.12..1.12 rows=17 width=62) (actual time=30.502..30.502 rows=24 loops=1)         Buckets: 1024  Batches: 1  Memory Usage: 9kB         ->  CTE Scan on t1  (cost=0.00..1.12 rows=17 width=62) (actual time=0.168..30.445 rows=24 loops=1)               Filter: (id < 100)               Rows Removed by Filter: 2476 Planning Time: 7.673 ms Execution Time: 49.284 ms(14 rows)

如果希望优化器把尽可能的把CTE视为内联查询进行优化,则指定NOT MATERIALIZED Option:
下面的查询,CTE被引用多次,优化器默认会进行MATERIALIZED,通过指定NOT MATERIALIZED则强制为内联查询.

testdb=# explain analyze WITH t1 AS ( SELECT * FROM t_w1 WHERE t_w1.id % 4 = 0 ) testdb-# SELECT * FROM t1 testdb-#   JOIN t_w2 as t2 testdb-#   ON t2.id = t1.idtestdb-# UNION ALLtestdb-# select t1.*,NULL,NULL from t1 where t1.id % 3 = 0;                                                      QUERY PLAN                                                       ----------------------------------------------------------------------------------------------------------------------- Append  (cost=205.62..399.89 rows=101 width=70) (actual time=11.663..27.725 rows=3332 loops=1)   CTE t1     ->  Seq Scan on t_w1  (cost=0.00..204.00 rows=50 width=8) (actual time=0.032..7.300 rows=2500 loops=1)           Filter: ((id % 4) = 0)           Rows Removed by Filter: 7500   ->  Hash Join  (cost=1.62..193.12 rows=100 width=70) (actual time=11.662..24.094 rows=2499 loops=1)         Hash Cond: (t2.id = t1.id)         ->  Seq Scan on t_w2 t2  (cost=0.00..153.00 rows=10000 width=8) (actual time=0.033..4.412 rows=10000 loops=1)         ->  Hash  (cost=1.00..1.00 rows=50 width=62) (actual time=11.611..11.612 rows=2500 loops=1)               Buckets: 4096 (originally 1024)  Batches: 1 (originally 1)  Memory Usage: 132kB               ->  CTE Scan on t1  (cost=0.00..1.00 rows=50 width=62) (actual time=0.035..9.916 rows=2500 loops=1)   ->  CTE Scan on t1 t1_1  (cost=0.00..1.25 rows=1 width=98) (actual time=0.008..2.824 rows=833 loops=1)         Filter: ((id % 3) = 0)         Rows Removed by Filter: 1667 Planning Time: 2.358 ms Execution Time: 28.746 ms(16 rows)

使用NOT MATERIALIZED选项

testdb=# explain analyze WITH t1 AS NOT MATERIALIZED( SELECT * FROM t_w1 WHERE t_w1.id % 4 = 0 ) SELECT * FROM t1   JOIN t_w2 as t2   ON t2.id = t1.idUNION ALLselect t1.*,NULL,NULL from t1 where t1.id % 3 = 0;                                                      QUERY PLAN                                                       ------------------------------------------------------------------------------------------- Append  (cost=204.62..650.39 rows=51 width=17) (actual time=27.894..57.453 rows=3332 loops=1)   ->  Hash Join  (cost=204.62..395.62 rows=50 width=16) (actual time=27.892..48.911 rows=2499 loops=1)         Hash Cond: (t2.id = t_w1.id)         ->  Seq Scan on t_w2 t2  (cost=0.00..153.00 rows=10000 width=8) (actual time=0.149..7.606 rows=10000 loops=1)         ->  Hash  (cost=204.00..204.00 rows=50 width=8) (actual time=27.699..27.699 rows=2500 loops=1)               Buckets: 4096 (originally 1024)  Batches: 1 (originally 1)  Memory Usage: 132kB               ->  Seq Scan on t_w1  (cost=0.00..204.00 rows=50 width=8) (actual time=0.151..22.446 rows=2500 loops=1)                     Filter: ((id % 4) = 0)                     Rows Removed by Filter: 7500   ->  Seq Scan on t_w1 t_w1_1  (cost=0.00..254.00 rows=1 width=44) (actual time=0.038..7.400 rows=833 loops=1)         Filter: (((id % 4) = 0) AND ((id % 3) = 0))         Rows Removed by Filter: 9167 Planning Time: 12.357 ms Execution Time: 58.490 ms(14 rows)

到此,关于"PostgreSQL新特性分析"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

查询 特性 分析 谓词 学习 更多 帮助 实用 视而不见 接下来 三个 副作用 可读性 围栏 子句 尽可能 情况 意味 手段 文章 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 网络安全伪造文件 规模大的浪潮服务器代理商在哪里 软件开发外包合同模板质量验收 读网络安全报告体会 兰州市雁东路小学网络安全 网络安全的书新人 互联网金融中的现代科技 学院网络安全生产法新闻稿 连接远程数据库 外网 广州伯纳斯互联网科技公司 长沙晨舟网络技术有限公司 怎么sql数据库 丽水云软件开发是做什么的 服务器机柜介绍 怎样向公司提供软件开发的想法 用数据库实现淘宝用户推送 如何从数据库中提取日期 大连数码广场软件开发公司 手机软件开发和电脑有相似吗 网络安全教育讲座手抄报 软件开发外包合同模板质量验收 舟山云软件开发费用 宝德ai服务器存量 服务器拒绝接受请求地址啥意思 数据库ch3 东西湖网络安全学院在哪里 高级数据库技术自考习题 视频传输管理服务器 md5数据库万能密码 网络安全手抄报字少图多
0