PostgreSQL 12.4 查询规划器忽略子分区约束,导致 table 扫描

PostgreSQL 12.4 query planner ignores sub-partition constraint, resulting in table scan

我有一个table

T (A int, B int, C long, D varchar)

由每个 A 分区并由每个 B 进行子分区(即列出每个分区都有一个值)。 A 的基数 <10,B 的基数 <100。 T 大约有 60 亿行。

当我运行查询

select distinct B from T where A = 1;

它 p运行es 顶级分区(A != 1 的分区)但对所有子分区执行 table 扫描以找到 [=14= 的不同值].我认为它会知道,基于分区设计,它只需要检查分区约束来确定给定 AB 的可能值,但可惜,事实并非如此。

AB 上没有索引,但每个分区的 (C,D) 上都有一个主键,这似乎无关紧要,但我想我应该提一下。我在 C 上也有一个 BRIN 索引。知道为什么 Postgres 查询规划器不参考子分区约束来避免 table 扫描吗?

原因是没有人在查询规划器中实现这样的优化。我不能说这让我感到惊讶,因为这是一个相当不寻常的查询。优化器中内置的每一个这样的优化都意味着分区 table 上具有 DISTINCT 的每个查询都需要一些额外的查询计划时间,而只有少数查询会获利。除了编写和维护代码的费用外,这对大多数用户来说都是净损失。

或许您可以使用元数据查询:

CREATE TABLE list (id bigint NOT NULL, p integer NOT NULL) PARTITION BY LIST (p);
CREATE TABLE list_42 PARTITION OF list FOR VALUES IN (42);
CREATE TABLE list_101 PARTITION OF list FOR VALUES IN (101);

SELECT regexp_replace(
          pg_get_expr(
             p.relpartbound,
             p.oid
          ),
          '^FOR VALUES IN \((.*)\)$',
          ''
       )::integer
FROM pg_class AS p
   JOIN pg_inherits AS i ON p.oid = i.inhrelid
WHERE i.inhparent = 'list'::regclass;

 regexp_replace 
----------------
             42
            101
(2 rows)