Skip to content

Partman behaves unexpectedly when partition size is changed, leaving gaps #809

@smcgivern

Description

@smcgivern

We have a table using ID-based partitioning where we want to dynamically change the partition size such that it's approximately a week's worth of data.

When we increase the partition size and run maintenance, new partitions get created based on the start of the latest existing partition, leaving gaps. An example is probably easiest:

CREATE SCHEMA partman;
CREATE EXTENSION IF NOT EXISTS pg_partman WITH SCHEMA partman;
CREATE TABLE test (id BIGSERIAL PRIMARY KEY, text text) PARTITION BY RANGE (id);
CREATE INDEX test_created_at ON test (id);
CREATE TABLE test_template (LIKE test);

SELECT partman.create_parent(
  p_parent_table => 'public.test',
  p_template_table => 'public.test',
  p_default_table => FALSE,
  p_control => 'id',
  p_interval => '10',
  p_premake => 1
);
foo=# \d+ test
                                                 Partitioned table "public.test"
 Column |  Type  | Collation | Nullable |             Default              | Storage  | Compression | Stats target | Description
--------+--------+-----------+----------+----------------------------------+----------+-------------+--------------+-------------
 id     | bigint |           | not null | nextval('test_id_seq'::regclass) | plain    |             |              |
 text   | text   |           |          |                                  | extended |             |              |
Partition key: RANGE (id)
Indexes:
    "test_pkey" PRIMARY KEY, btree (id)
    "test_created_at" btree (id)
Partitions: test_p0 FOR VALUES FROM ('0') TO ('10'),
            test_p10 FOR VALUES FROM ('10') TO ('20')
UPDATE partman.part_config SET partition_interval = 100 WHERE parent_table = 'public.test';
INSERT INTO test (text) VALUES ('a'), ('b'), ('c'), ('d'), ('e'), ('f'), ('g'), ('h'), ('i'), ('j');
CALL partman.run_maintenance_proc();
foo=# \d+ test
                                                 Partitioned table "public.test"
 Column |  Type  | Collation | Nullable |             Default              | Storage  | Compression | Stats target | Description
--------+--------+-----------+----------+----------------------------------+----------+-------------+--------------+-------------
 id     | bigint |           | not null | nextval('test_id_seq'::regclass) | plain    |             |              |
 text   | text   |           |          |                                  | extended |             |              |
Partition key: RANGE (id)
Indexes:
    "test_pkey" PRIMARY KEY, btree (id)
    "test_created_at" btree (id)
Partitions: test_p0 FOR VALUES FROM ('0') TO ('10'),
            test_p10 FOR VALUES FROM ('10') TO ('20'),
            test_p110 FOR VALUES FROM ('110') TO ('210'),
            test_p210 FOR VALUES FROM ('210') TO ('310')

No partition covers the range 20-110! Is this expected? I appreciate that changing partition size dynamically may not be typical usage, but this was quite surprising to us. We had to manually create a partition to fill in the gap like so:

CREATE TABLE test_p20 (LIKE test INCLUDING COMMENTS INCLUDING COMPRESSION INCLUDING CONSTRAINTS INCLUDING DEFAULTS INCLUDING GENERATED INCLUDING STATISTICS INCLUDING STORAGE);
SELECT partman.inherit_template_properties('public.test', 'public', 'test_p20');
ALTER TABLE test ATTACH PARTITION test_p20 FOR VALUES FROM ('20') TO ('110');

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions