【问题标题】:Postgres Inheritance based partition scanning all the partitions基于 Postgres 继承的分区扫描所有分区
【发布时间】:2021-08-26 12:43:18
【问题描述】:

我想通过 Postgres 中的继承来实现分区。 我通过参考 Postgres article 实现了以下步骤:-

  1. 创建了一个名为“test_table”的主表
CREATE TABLE kirana_customer.test_table
(
    col1 bigint NOT NULL DEFAULT nextval('kirana_customer."testTable_col1_seq"'::regclass),
    col2 bigint NOT NULL,
    col3 integer,
    CONSTRAINT "testTable_pkey" PRIMARY KEY (col1)
)
  1. 创建了子表/继承表
CREATE TABLE kirana_customer.test_table_1
(
    -- Inherited from table kirana_customer.test_table: col1 bigint NOT NULL DEFAULT nextval('kirana_customer."testTable_col1_seq"'::regclass),
    -- Inherited from table kirana_customer.test_table: col2 bigint NOT NULL,
    -- Inherited from table kirana_customer.test_table: col3 integer,
    CONSTRAINT check_col3 CHECK (col3 = 1)
)
    INHERITS (kirana_customer.test_table)
  1. 将“BEFORE INSERT”触发器附加到主表,以便将基于列“col3”的数据插入到正确的分区表中
DECLARE

    v_col3 bigint;
BEGIN
    v_col3 := NEW.col3;
    
    
    EXECUTE 'INSERT INTO kirana_customer.test_table_'||v_col3||' VALUES ($1.*)' USING NEW;

RETURN NULL;
END;

完成所有这些步骤后,我可以将我的条目插入正确的分区,但是在分析 select 语句时,我发现 Postgres 正在扫描所有分区

explain select * from  kirana_customer.test_table where col3 = 1 

这给出了以下输出

"Append  (cost=0.00..34.42 rows=9 width=20)"
"  ->  Seq Scan on test_table  (cost=0.00..3.12 rows=1 width=20)"
"        Filter: (col3 = 1)"
"  ->  Seq Scan on test_table_1  (cost=0.00..31.25 rows=8 width=20)"
"        Filter: (col3 = 1)"

那么,我错过了什么吗?或者这就是 Postgres 分区的工作方式?

【问题讨论】:

  • "我想通过继承实现分区" - 为什么?使用 Postres 12,您应该使用声明性分区。更高效,更好地集成到查询优化器中
  • 如果我的分区键不是主键或复合主键,则声明性分区不允许我创建分区。我也无法使用外键。所以,我选择使用继承基础分区
  • 您也不能将外键与基于继承的分区一起使用。而且你也不能在所有继承的表中都有一个正确的主键。
  • 但我仍然可以使用不是 PK 或复合 PK 的分区键。我知道声明性分区是新的并且很容易使用。但是,不应该基于继承的分区工作吗?
  • 基于继承的分区一直是穷人的分区实现。没有很好地集成到查询优化器中,而且它从来没有达到应有的效果。诚然,您可能能够使用不属于 PK 的分区键 - 但 PK 本身并不是真正的(全局)PK。

标签: postgresql database-partitioning postgres-12


【解决方案1】:

你不能用 1 的样本量得出结论。而且你只有一个子表。

没有限制根表不能包含行where col3=1,所以需要扫描。扫描一个空的able并不是什么大问题,但如果你确实想避免它,你可以添加一个约束:

alter table kirana_customer.test_table add constraint whatever
   check (col3 is null) no inherit; 

此外,您不想使用声明性分区的理由没有任何意义。也许你应该用一个例子来问一个关于你对此有什么误解的问题。

【讨论】:

  • 添加约束后,不扫描父表。谢谢!!!
【解决方案2】:

您必须将 constraint_exclusion 设置为 onpartition 才能工作。

【讨论】:

  • constraint_exclusion 已设置为 partition 。一旦我按照上一个答案中的说明设置约束,它就会停止扫描父表。不管怎样,谢谢你的帮助!!
猜你喜欢
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
  • 2011-08-03
  • 2015-03-06
相关资源
最近更新 更多