文章目录

  • 智能分区连接
  • 智能分区聚合

PostgreSQL 11 提供了两个分区级别的新功能:

  • 智能分区连接(partition-wise join),对于两个分区方式相同的分区表,如果使用分区键进行等值连接,允许使用匹配的分区直接进行连接操作。
  • 智能分区聚合(partition-wise aggregation),对于分区表的聚合操作,如果 GROUP BY 中包含了分区键,允许针对各个分区进行并行的聚合操作,然后再合并结果。

智能分区连接

PostgreSQL 11 增加了一个新的选项:enable_partitionwise_join,用于控制查询计划器是否使用分区级别的连接。默认值为 off。

首先,创建两个分区表,它们使用相同的分区方式:

CREATE TABLE prt1 (a int, b int, c varchar) PARTITION BY RANGE(a);
CREATE TABLE prt1_p1 PARTITION OF prt1 FOR VALUES FROM (0) TO (250);
CREATE TABLE prt1_p3 PARTITION OF prt1 FOR VALUES FROM (500) TO (600);
CREATE TABLE prt1_p2 PARTITION OF prt1 FOR VALUES FROM (250) TO (500);
INSERT INTO prt1 SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(0, 599) i WHERE i % 2 = 0;
CREATE INDEX iprt1_p1_a on prt1_p1(a);
CREATE INDEX iprt1_p2_a on prt1_p2(a);
CREATE INDEX iprt1_p3_a on prt1_p3(a);
ANALYZE prt1;CREATE TABLE prt2 (a int, b int, c varchar) PARTITION BY RANGE(b);
CREATE TABLE prt2_p1 PARTITION OF prt2 FOR VALUES FROM (0) TO (250);
CREATE TABLE prt2_p2 PARTITION OF prt2 FOR VALUES FROM (250) TO (500);
CREATE TABLE prt2_p3 PARTITION OF prt2 FOR VALUES FROM (500) TO (600);
INSERT INTO prt2 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(0, 599) i WHERE i % 3 = 0;
CREATE INDEX iprt2_p1_b on prt2_p1(b);
CREATE INDEX iprt2_p2_b on prt2_p2(b);
CREATE INDEX iprt2_p3_b on prt2_p3(b);
ANALYZE prt2;

查看默认情况下,两个表的连接操作:

show enable_partitionwise_join;enable_partitionwise_join
---------------------------off
(1 row)EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b;QUERY PLAN
--------------------------------------------------SortSort Key: t1.a->  Hash JoinHash Cond: (t2.b = t1.a)->  Append->  Seq Scan on prt2_p1 t2->  Seq Scan on prt2_p2 t2_1->  Seq Scan on prt2_p3 t2_2->  Hash->  Append->  Seq Scan on prt1_p1 t1Filter: (b = 0)->  Seq Scan on prt1_p2 t1_1Filter: (b = 0)->  Seq Scan on prt1_p3 t1_2Filter: (b = 0)
(16 rows)

默认情况下,需要先分别扫描两个表的所有分区,将分区结果分别整合在一起(Append),然后执行两个表的哈希连接(Hash Join),最后进行排序(Sort)。

接下来,启用智能分区连接功能,即将参数 enable_partitionwise_join 设置为 on。再次查看相同的连接操作:

set enable_partitionwise_join to true;
SET
rgsdb=# show enable_partitionwise_join;enable_partitionwise_join
---------------------------on
(1 row)EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b;QUERY PLAN
--------------------------------------------------SortSort Key: t1.a->  Append->  Hash JoinHash Cond: (t2.b = t1.a)->  Seq Scan on prt2_p1 t2->  Hash->  Seq Scan on prt1_p1 t1Filter: (b = 0)->  Hash JoinHash Cond: (t2_1.b = t1_1.a)->  Seq Scan on prt2_p2 t2_1->  Hash->  Seq Scan on prt1_p2 t1_1Filter: (b = 0)->  Hash JoinHash Cond: (t2_2.b = t1_2.a)->  Seq Scan on prt2_p3 t2_2->  Hash->  Seq Scan on prt1_p3 t1_2Filter: (b = 0)
(21 rows)

可以看到,启用该功能之后,先针对两个表中的相应分区执行哈希连接(Hash Join),然后将结果整合在一起(Append),最后进行排序(Sort)。其中,分区级别的哈希连接可以并行执行,而且分区中的数据量比整个表少,性能会更好。

目前,智能分区连接要求连接条件中必须包含所有的分区字段,它们的数据类型必须相同,并且分区方式一致。由于智能分区连接的计划阶段需要占用更多的 CPU 时间和内存,默认没有启用该功能。

智能分区聚合

智能分区聚合(分组)使用选项 enable_partitionwise_aggregate 进行控制。默认值为 off。

首先,创建一个分区表:

CREATE TABLE pagg_tab (a int, b int, c text, d int) PARTITION BY LIST(c);
CREATE TABLE pagg_tab_p1 PARTITION OF pagg_tab FOR VALUES IN ('0000', '0001', '0002', '0003');
CREATE TABLE pagg_tab_p2 PARTITION OF pagg_tab FOR VALUES IN ('0004', '0005', '0006', '0007');
CREATE TABLE pagg_tab_p3 PARTITION OF pagg_tab FOR VALUES IN ('0008', '0009', '0010', '0011');
INSERT INTO pagg_tab SELECT i % 20, i % 30, to_char(i % 12, 'FM0000'), i % 30 FROM generate_series(0, 2999) i;
ANALYZE pagg_tab;

默认情况下的聚合操作:

show enable_partitionwise_aggregate;enable_partitionwise_aggregate
--------------------------------off
(1 row)EXPLAIN (COSTS OFF)
SELECT c, sum(a), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY c HAVING avg(d) < 15 ORDER BY 1, 2, 3;QUERY PLAN
-----------------------------------------------------------------------SortSort Key: pagg_tab_p1.c, (sum(pagg_tab_p1.a)), (avg(pagg_tab_p1.b))->  HashAggregateGroup Key: pagg_tab_p1.cFilter: (avg(pagg_tab_p1.d) < '15'::numeric)->  Append->  Seq Scan on pagg_tab_p1->  Seq Scan on pagg_tab_p2->  Seq Scan on pagg_tab_p3
(9 rows)

默认情况下,需要先分别扫描表的所有分区,将分区结果整合在一起(Append),然后执行哈希聚合(HashAggregate),最后进行排序(Sort)。

启用智能分区聚合功能,查看相同的聚合操作:

SET enable_partitionwise_aggregate TO true;
SETEXPLAIN (COSTS OFF)
SELECT c, sum(a), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY c HAVING avg(d) < 15 ORDER BY 1, 2, 3;QUERY PLAN
-----------------------------------------------------------------------SortSort Key: pagg_tab_p1.c, (sum(pagg_tab_p1.a)), (avg(pagg_tab_p1.b))->  Append->  HashAggregateGroup Key: pagg_tab_p1.cFilter: (avg(pagg_tab_p1.d) < '15'::numeric)->  Seq Scan on pagg_tab_p1->  HashAggregateGroup Key: pagg_tab_p2.cFilter: (avg(pagg_tab_p2.d) < '15'::numeric)->  Seq Scan on pagg_tab_p2->  HashAggregateGroup Key: pagg_tab_p3.cFilter: (avg(pagg_tab_p3.d) < '15'::numeric)->  Seq Scan on pagg_tab_p3
(15 rows)

可以看到,启用该功能之后,先针对表中的所有分区执行哈希聚合(HashAggregate),然后将结果整合在一起(Append),最后进行排序(Sort)。其中,分区级别的聚合可以并行执行,性能会更好。

如果 GROUP BY 子句中没有包含分区字段,只会基于分区执行部分聚合操作,然后再对结果进行一次最终的聚合。

以下查询使用字段 a 进行分组聚合:

EXPLAIN (COSTS OFF)
SELECT a, sum(b), avg(b), count(*), min(a), max(b) FROM pagg_tab GROUP BY a HAVING avg(d) < 15 ORDER BY 1, 2, 3;QUERY PLAN
-----------------------------------------------------------------------SortSort Key: pagg_tab_p1.a, (sum(pagg_tab_p1.b)), (avg(pagg_tab_p1.b))->  Finalize HashAggregateGroup Key: pagg_tab_p1.aFilter: (avg(pagg_tab_p1.d) < '15'::numeric)->  Append->  Partial HashAggregateGroup Key: pagg_tab_p1.a->  Seq Scan on pagg_tab_p1->  Partial HashAggregateGroup Key: pagg_tab_p2.a->  Seq Scan on pagg_tab_p2->  Partial HashAggregateGroup Key: pagg_tab_p3.a->  Seq Scan on pagg_tab_p3
(15 rows)

由于字段 a 不是分区键,所以先执行分区级别的部分哈希聚合(Partial HashAggregate),聚合的结果中可能存在相同的分组(不同分区中的字段 a 存在相同的值),需要执行最终的哈希聚合(Finalize HashAggregate)操作。

由于智能分区聚合(分组)的计划阶段需要占用更多的 CPU 时间和内存,默认没有启用该功能。

可以同时启用智能分区连接与智能分区聚合功能。首先,创建两个分区表:

CREATE TABLE pagg_tab1(x int, y int) PARTITION BY RANGE(x);
CREATE TABLE pagg_tab1_p1 PARTITION OF pagg_tab1 FOR VALUES FROM (0) TO (10);
CREATE TABLE pagg_tab1_p2 PARTITION OF pagg_tab1 FOR VALUES FROM (10) TO (20);
CREATE TABLE pagg_tab1_p3 PARTITION OF pagg_tab1 FOR VALUES FROM (20) TO (30);CREATE TABLE pagg_tab2(x int, y int) PARTITION BY RANGE(y);
CREATE TABLE pagg_tab2_p1 PARTITION OF pagg_tab2 FOR VALUES FROM (0) TO (10);
CREATE TABLE pagg_tab2_p2 PARTITION OF pagg_tab2 FOR VALUES FROM (10) TO (20);
CREATE TABLE pagg_tab2_p3 PARTITION OF pagg_tab2 FOR VALUES FROM (20) TO (30);INSERT INTO pagg_tab1 SELECT i % 30, i % 20 FROM generate_series(0, 299, 2) i;
INSERT INTO pagg_tab2 SELECT i % 20, i % 30 FROM generate_series(0, 299, 3) i;ANALYZE pagg_tab1;
ANALYZE pagg_tab2;

使用分区字段作为连接条件,同时使用分区字段进行分组聚合:

SET enable_partitionwise_join TO true;
SET enable_partitionwise_aggregate TO true;EXPLAIN (COSTS OFF)
rgsdb-# SELECT t1.x, sum(t1.y), count(*) FROM pagg_tab1 t1, pagg_tab2 t2 WHERE t1.x = t2.y GROUP BY t1.x ORDER BY 1, 2, 3;QUERY PLAN
-------------------------------------------------------------SortSort Key: t1.x, (sum(t1.y)), (count(*))->  Append->  HashAggregateGroup Key: t1.x->  Hash JoinHash Cond: (t1.x = t2.y)->  Seq Scan on pagg_tab1_p1 t1->  Hash->  Seq Scan on pagg_tab2_p1 t2->  HashAggregateGroup Key: t1_1.x->  Hash JoinHash Cond: (t1_1.x = t2_1.y)->  Seq Scan on pagg_tab1_p2 t1_1->  Hash->  Seq Scan on pagg_tab2_p2 t2_1->  HashAggregateGroup Key: t1_2.x->  Hash JoinHash Cond: (t2_2.y = t1_2.x)->  Seq Scan on pagg_tab2_p3 t2_2->  Hash->  Seq Scan on pagg_tab1_p3 t1_2
(24 rows)

执行计划先针对两个表中的相应分区执行哈希连接(Hash Join),然后基于连接结果执行分区级别的哈希聚合(HashAggregate),将结果整合在一起(Append),最后进行排序(Sort)。分区级别的哈希连接以及分区级别的聚合可以并行执行。

另外,PostgreSQL 11 还支持 postgres_fdw 外部分区的聚合操作下推,即将聚合操作下推至外部表执行。同时还支持 postgres_fdw 外部分区上的 INSERT、UPDATE、COPY 操作。

参考:
Basic partition-wise join functionality.
Implement partition-wise grouping/aggregation.

人生本来短暂,你又何必匆匆!点个赞再走吧!

PotgreSQL 11 新特性之智能分区连接/聚合相关推荐

  1. this指针_c++11新特性之智能指针

    很多人谈到c++,说它特别难,可能有一部分就是因为c++的内存管理吧,不像java那样有虚拟机动态的管理内存,在程序运行过程中可能就会出现内存泄漏,然而这种问题其实都可以通过c++11引入的智能指针来 ...

  2. C++11新特性之智能指针

    智能指针的特性 智能指针可以自动释放不再使用的内存,能够有效的防止内存泄漏. 智能指针是一个对象,普通指针是一个变量. 智能指针是对普通指针的封装,其安全性要高于直接使用普通指针. 智能指针的分类 共 ...

  3. 深入浅出之C++11新特性

    1. auto类型赋予新含义 1.1 auto类型定义 在之前的 C++ 版本中,auto 关键字用来指明变量的存储类型,它和 static 关键字是相对的.auto 表示变量是自动存储的,这也是编译 ...

  4. 【C++11新特性】 C++11智能指针之weak_ptr

    http://blog.csdn.net/xiejingfa/article/details/50772571 原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/ar ...

  5. c++11新特性_【C++11新特性】 C++11智能指针之weak_ptr

    如题,我们今天要讲的是 C++11 引入的三种智能指针中的:weak_ptr. 在学习 weak_ptr 之前最好对 shared_ptr 有所了解.如果你还不知道 shared_ptr 是何物,可以 ...

  6. C++11新特性(原封不动转载待查)

    C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...

  7. 《深入理解C++11:C++ 11新特性解析与应用》——导读

    前 言 为什么要写这本书 相比其他语言的频繁更新,C++语言标准已经有十多年没有真正更新过了.而上一次标准制定,正是面向对象概念开始盛行的时候.较之基于过程的编程语言,基于面向对象.泛型编程等概念的C ...

  8. C++11新特性的总结

    C++11新特性 auto关键字(C++11)基于范围的for循环(C++11). 指针空值nullptr(C++11) C++动态内存管理 序列式容器 array forward_list; 继承和 ...

  9. C++11新特性以及std::thread多线程编程

    一 .C++11新特性 1. auto 类型推导 1.1 当=号右边的表达式是一个引用类型时,auto会把引用抛弃,直接推导出原始类型: 1.2 当=号右边的表达式带有const属性时,auto不会使 ...

最新文章

  1. 详细通俗重点CRF层讲解
  2. Thread类和Runable接口使用
  3. Scala中的延迟初始化(Lazy vals)
  4. ASP.NET中的Eval()和DataBinder.Eval()方法
  5. Multi-thread--提高C++性能的编程技术笔记:多线程内存池+测试代码
  6. body-content取值的意义
  7. iis端口号 linux,Linux 6 修改ssh默认远程端口号的操作步骤
  8. 一种使用pyinstaller时图标问题解决方案
  9. bzoj3545/bzoj3551 [ONTAK2010]Peaks/Peaks加强版
  10. 两侧列固定中间列变宽Div布局参考
  11. 开发APP软件需要哪些编程语言和开发环境
  12. 【百度头条】精准微营销—本地离线92GBQQ群数据库,包含全部版本
  13. 未来机器人背景的AI人工智能PPT模板
  14. minus用法c语言,Minus-C 一个最小化的C语言规范
  15. 除了中国知网和谷歌文学还有哪些好的有权威的资源站?
  16. python与人工智能有关系吗_Python与人工智能到底有什么关系呢?Python学习
  17. Ubuntu系统如何用网线连上路由器上网
  18. Kafka的命令行操作
  19. openwrt系统下修改网关_OpenWRT路由配置技巧
  20. 软件企业成本管理及工时管理调查表

热门文章

  1. Dew Lab Studio
  2. 2021年山东省安全员B证试题及解析及山东省安全员B证复审模拟考试
  3. 小程序游戏开发有哪些游戏引擎可以选择?
  4. 微信小游戏开发(1)
  5. 高通导航器软件开发包使用指南(13)
  6. git常用命令-进阶
  7. 今年做什么副业好?2021年做什么副业挣钱?2021年适合做的副业
  8. 【转】程序设计语言中的 一等公民,二等公民,三等公民
  9. 5.1环绕声是什么意思
  10. Windows server 2008、2012、2016搭建sftp服务(超级简单)