本文介绍了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,默认值为32(即当分区表的分区数量大于32个时,将会自动启用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.266ms | 0.067ms |
32 | 1.820ms | 0.258ms |
64 | 3.654ms | 0.402ms |
128 | 7.010ms | 0.664ms |
256 | 14.095ms | 1.247ms |
512 | 27.697ms | 2.328ms |
1024 | 73.176ms | 4.165ms |
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进行一定程度的优化。