Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to use postgres table partitioning with overlapping constraints?

Postgres documentation says that conditions in table partitions should not overlap

Ensure that the constraints guarantee that there is no overlap between the key values permitted in different partitions.

but I don't understand why, because exact partition that data has to be inserted into is still decided by trigger, which might be aware of overlapping constraints

I have the following situation, a table with a lot of text information and update_date time stamp, this table is partitioned by quarter, and all new or updated rows go into the newest partition, the problem is that gin trigram index is too slow, so I want to avoid building trigram index for the current day

currently trigger on the master table is responsible for creating partitions dynamically, I'm planning to add new partition for the current day, which will overlap with the quarter partition, and I want to disable trigram index for the current day partition (merging data back into quarter partition would be another maintenance task)

I've tried creating partition tables manually with overlapping update_date constraints and postgres didn't complain, I even did search and both tables were used in the plan, so it seems to work just fine, yet documentation says that constraints can't overlap, why is that?

is it safe to create partitions with overlapping constraint if I have proper triggers and maintenance?

UPD:

CREATE TABLE master (text_value text, update_date timestamp);

CREATE TABLE partition_year (
    CHECK ( update_date >= DATE '2015-01-01' AND update_date < DATE '2015-12-31' )
) INHERITS (master);

CREATE TABLE partition_month (
    CHECK ( update_date >= DATE '2015-07-01' AND update_date < DATE '2015-8-01' )
) INHERITS (master);

-- in production this would be handled by trigger
insert into partition_year(text_value, update_date) values ('year', '2015-01-02');
insert into partition_month(text_value, update_date) values ('month', '2015-07-02');

-- this scans only year partition
explain select * from master where update_date = '2015-01-02';

-- this scans both year and month partition
explain select * from master where update_date = '2015-07-02';

this example shows that postgres reads both year and month partititon and doesn't care much about their overlap

like image 548
Gruzilkin Avatar asked Jul 22 '15 04:07

Gruzilkin


1 Answers

As of PostgreSQL 11, there is a simple answer:

It won't let you do that.

create table tbl_partitioned (
  part_id int primary key
) partition by range (part_id);

create table tbl_partition_1_to_5 partition of tbl_partitioned for values from (1) to (5);
create table tbl_partition_4_to_9 partition of tbl_partitioned for values from (4) to (9);

-- ERROR:  partition "tbl_partition_4_to_9" would overlap partition "tbl_partition_1_to_5"

Here's the complete dbfiddle.

like image 79
blubb Avatar answered Aug 29 '23 00:08

blubb