【问题标题】:PostgreSQL 12.4 query planner ignores sub-partition constraint, resulting in table scanPostgreSQL 12.4 查询计划器忽略子分区约束,导致表扫描
【发布时间】:2020-09-30 20:50:45
【问题描述】:

我有一张桌子

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

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

当我运行查询时

select distinct B from T where A = 1;

它会修剪顶级分区(A != 1 所在的分区),但会对所有子分区执行表扫描以查找 B 的不同值。我以为它会知道,基于分区设计,它只需要检查分区约束来确定给定AB 的可能值,但可惜,事实并非如此。

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

【问题讨论】:

    标签: postgresql postgresql-12 query-planner


    【解决方案1】:

    原因是没有人在查询计划器中实现这样的优化。我不能说这让我感到惊讶,因为这是一个相当不寻常的查询。优化器中内置的每个此类优化都意味着对具有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 \((.*)\)$',
              '\1'
           )::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)
    

    【讨论】:

      猜你喜欢
      • 2013-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-13
      相关资源
      最近更新 更多