Search code examples
postgresqldatabase-partitioningpostgres-12

Postgres Inheritance based partition scanning all the partitions


I wanted to implement partitioning via inheritance in Postgres. I implemented the below steps by referring to the Postgres article :-

  1. Created a master table called "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. Created the child/inherited table
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. Attached a "BEFORE INSERT" trigger to the master table for inserting data based on column "col3" to the correct partition table
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;

After completing all these steps i am able to insert my entries into the correct partition , but while analysing the select statements i found that Postgres is scanning all the partitions

explain select * from  kirana_customer.test_table where col3 = 1 

This gives the below output

"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)"

So, did I miss something? Or is this the way Postgres partitioning works?


Solution

  • You can't really draw conclusions with a sample size of 1. And you only have one child table.

    There is no constraint that the root table cannot contain rows where col3=1, so it needs to be scanned. Scanning an empty able is not a big deal, but if you did want to avoid it you could add a constraint:

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

    Also, your reason for not wanting to use declarative partitioning doesn't make any sense. Maybe you should ask a question with an example about whatever misconception you have about that.