本文介绍了PartitionedTable Scan Node的使用方法以及性能对比等内容。
背景信息
查询算子Append是分区表的常用算子,但是它的性能低下,为了解决这个问题,PolarDB推出了PartitionedTable Scan算子,它是一个分区表的查询算子,比Append更加高效。用于解决分区表分区数量过多时,查询性能慢的问题。
使用限制
- PolarDB PostgreSQL版(兼容Oracle)内核小版本需为V1.1.32及以上。 
- PartitionedTableScan目前仅支持 - select,不支持DML语句。
- PartitionedTableScan不支持partitionwise_join,如果您开启了enable_partitionwise_join,将不会生成PartitionedTableScan plan。 
- PartitionedTableScan不支持并行。 
注意事项
PartitionedTable Scan Node功能仅适用于内核小版本为V1.1.32及以上的集群,存量集群请联系我们,进行开启。
使用指南
创建一张分区表。
CREATE TABLE prt1 (a int, b int, c varchar) PARTITION BY Hash(a) partitions 16;通过参数启用PartitionedTableScan算子
当一张分区表的子分区数量大于polar_num_parts_for_partitionedscan参数值时,会生成PartitionedTableScan算子。polar_num_parts_for_partitionedscan参数取值范围:-1~INT_MAX,默认值为64(即当分区表的分区数量大于64个时,将会自动启用PartitionedTableScan算子)。
- 当 - polar_num_parts_for_partitionedscan=-1时,将启用PartitionedTableScan算子,不管分区表的分区数量是多少。
- 当 - polar_num_parts_for_partitionedscan=0时,不会启用PartitionedTableScan算子,不管分区表的分区数量是多少。
示例如下:
SET polar_num_parts_for_partitionedscan to -1;
explain select * from prt1;
                           QUERY PLAN                            
-----------------------------------------------------------------
 PartitionedTableScan on prt1  (cost=0.00..1.00 rows=1 width=40)
   ->  Seq Scan on prt1  (cost=0.00..1.00 rows=1 width=40)
(2 rows)使用HINT
使用HINT语法PARTEDSCAN(table alias),示例如下:
EXPLAIN select /*+PARTEDSCAN(prt1) */ select * from prt1;
                           QUERY PLAN                            
-----------------------------------------------------------------
 PartitionedTableScan on prt1  (cost=0.00..1.00 rows=1 width=40)
   ->  Seq Scan on prt1  (cost=0.00..1.00 rows=1 width=40)
(2 rows)性能对比
PartitionedTableScan(PTS)相比于Append更加高效,以下是PTS和Append的性能对比:
准备测试SQL:
explain select  * from prt1 where b = 10; 
explain select /*+PARTEDSCAN(prt1) */ * from prt1 where b = 10;  以下测试数据不能作为性能标准数据,不同配置,不同条件下测试出的数据可能不同,此处为开发环境测试出的临时数据。测试目的是根据单一变量原则,环境配置一致的情况下,对比Append和PartitionedTableScan的性能差异。
单条SQL的plan time
| 分区数量 | Append plan time | PTS plan time | 
| 16 | 0.266 ms | 0.067 ms | 
| 32 | 1.820 ms | 0.258 ms | 
| 64 | 3.654 ms | 0.402 ms | 
| 128 | 7.010 ms | 0.664 ms | 
| 256 | 14.095 ms | 1.247 ms | 
| 512 | 27.697 ms | 2.328 ms | 
| 1024 | 73.176 ms | 4.165 ms | 
memory(单条SQL内存使用量)
| 分区数量 | Append mem | PTS mem | 
| 16 | 1,170 KB | 1,044 KB | 
| 32 | 1,240 KB | 1,044 KB | 
| 64 | 2,120 KB | 1,624 KB | 
| 128 | 2,244 KB | 1,524 KB | 
| 256 | 2,888 KB | 2,072 KB | 
| 512 | 4,720 KB | 3,012 KB | 
| 1024 | 8,236 KB | 5,280 KB | 
QPS(query per second)
pgbench -i --scale=10
pgbench -c 64 -j 64 -n -T60
Query:
	explain select  * from prt1 where b = 10; 
	explain select /*+PARTEDSCAN(prt1) */ * from prt1 where b = 10;  | 分区数量 | Append QPS | PTS QPS | 
| 16 | 25,318 | 93,950 | 
| 32 | 10,906 | 61,879 | 
| 64 | 5,281 | 30,839 | 
| 128 | 2,195 | 16,684 | 
| 256 | 920 | 8,372 | 
| 512 | 92 | 3,708 | 
| 1024 | 21 | 1,190 | 
结论
从上面的PartitionedTableScan和Append的对比而言,PartitionedTableScan相比于Append随着分区数量增加时,性能提升明显。如果您在业务中分区表分区的数量较多,且plantime很慢时,我们建议您使用PartitionedTableScan进行一定程度的优化。