PostgreSQL中的partition-wise aggregation

partition-wise aggregation容許對每一個分區分別執行的分區表進行分組或聚合。若是GROUP BY子句不包括分區鍵,則只能在每一個分區的基礎上執行部分聚合,而且必須稍後執行最終處理。因爲partitionwise分組或聚合可能在計劃期間佔用大量CPU時間和內存,所以默認設置爲關閉。sql

經過變量enable_partitionwise_aggregate控制是否啓用該特性。post

 

建立一個分區表,用於測試:性能

create table pagg_t (a int, b int, c text, d int) partition by list(c);
create table pagg_t_p1 partition of pagg_t for values in ('000', '001', '002', '003');
create table pagg_t_p2 partition of pagg_t for values in ('004', '005', '006', '007');
create table pagg_t_p3 partition of pagg_t for values in ('008', '009', '010', '011');
insert into pagg_t select i % 20, i % 30, to_char(i % 12, 'fm0000'), i % 30 from generate_series(0, 2999) i;
analyze pagg_t;

  

postgres=# show enable_partitionwise_aggregate;
 off

postgres=# explain (costs off) select c, sum(a), avg(b), count(*), min(a), max(b) from pagg_t group by c having avg(d) < 15 order by 1, 2, 3;
 Sort
   Sort Key: pagg_t_p1.c, (sum(pagg_t_p1.a)), (avg(pagg_t_p1.b))
   ->  HashAggregate
         Group Key: pagg_t_p1.c
         Filter: (avg(pagg_t_p1.d) < '15'::numeric)
         ->  Append
               ->  Seq Scan on pagg_t_p1
               ->  Seq Scan on pagg_t_p2
               ->  Seq Scan on pagg_t_p3

postgres=# 

默認狀況下,須要先分別掃描表的全部分區,將分區結果整合在一塊兒(Append),而後執行哈希聚合(HashAggregate),最後進行排序(Sort)。測試

啓用智能分區聚合功能,查看相同的聚合操做:blog

postgres=# set enable_partitionwise_aggregate=on;
SET
postgres=# show enable_partitionwise_aggregate;
 on

postgres=# explain (costs off) select c, sum(a), avg(b), count(*), min(a), max(b) from pagg_t group by c having avg(d) < 15 order by 1, 2, 3;
 Sort
   Sort Key: pagg_t_p1.c, (sum(pagg_t_p1.a)), (avg(pagg_t_p1.b))
   ->  Append
         ->  HashAggregate
               Group Key: pagg_t_p1.c
               Filter: (avg(pagg_t_p1.d) < '15'::numeric)
               ->  Seq Scan on pagg_t_p1
         ->  HashAggregate
               Group Key: pagg_t_p2.c
               Filter: (avg(pagg_t_p2.d) < '15'::numeric)
               ->  Seq Scan on pagg_t_p2
         ->  HashAggregate
               Group Key: pagg_t_p3.c
               Filter: (avg(pagg_t_p3.d) < '15'::numeric)
               ->  Seq Scan on pagg_t_p3

postgres=# 

能夠看到,啓用該功能以後,先針對表中的全部分區執行哈希聚合(HashAggregate),而後將結果整合在一塊兒(Append),最後進行排序(Sort)。其中,分區級別的聚合能夠並行執行,性能會更好。排序

若是GROUP BY子句中沒有包含分區字段,只會基於分區執行部分聚合操做,而後再對結果進行一次最終的聚合。內存

如下查詢使用字段 a 進行分組聚合:it

postgres=# explain (costs off) select a, sum(b), avg(b), count(*), min(a), max(b) from pagg_t group by a having avg(d) < 15 order by 1, 2, 3; 
 Sort
   Sort Key: pagg_t_p1.a, (sum(pagg_t_p1.b)), (avg(pagg_t_p1.b))
   ->  Finalize HashAggregate
         Group Key: pagg_t_p1.a
         Filter: (avg(pagg_t_p1.d) < '15'::numeric)
         ->  Append
               ->  Partial HashAggregate
                     Group Key: pagg_t_p1.a
                     ->  Seq Scan on pagg_t_p1
               ->  Partial HashAggregate
                     Group Key: pagg_t_p2.a
                     ->  Seq Scan on pagg_t_p2
               ->  Partial HashAggregate
                     Group Key: pagg_t_p3.a
                     ->  Seq Scan on pagg_t_p3

postgres=# 

因爲字段 a 不是分區鍵,因此先執行分區級別的部分哈希聚合(Partial HashAggregate),聚合的結果中可能存在相同的分組(不一樣分區中的字段 a 存在相同的值),須要執行最終的哈希聚合(Finalize HashAggregate)操做。io

相關文章
相關標籤/搜索