PostgreSQL 12: Added pg_partition_tree() function to display partition table information

Introduction: PostgreSQL 12 adds three new partition query functions, as follows: pg_partition_tree(regclass): Returns detailed information of the partition table, such as partition name, upper-level partition name, whether it is a leaf node, level, level 0 indicates the top-level parent table.

PostgreSQL 12 adds three new partition query functions, as follows:

  • pg_partition_tree(regclass): Returns the detailed information of the partition table, such as partition name, upper-level partition name, whether it is a leaf node, and level. Level 0 represents the top-level parent table.
  • pg_partition_ancestors(regclass): Returns the upper-level partition name, including the current-level partition name.
  • pg_partition_root(regclass): Returns the top-level parent table name.

Release Notes

Add partition introspection functions (Micha?l Paquier, álvaro Herrera, Amit Langote)

New function pg_partition_root() returns the top-most parent of a partition tree, pg_partition_ancestors() reports all ancestors of a partition, and pg_partition_tree() displays information about partitions.

Environment preparation: Create a two-dimensional partition table

Create the parent table as follows:

CREATE TABLE userinfo (
 userid int4,
 username character varying(64),
 ctime timestamp(6) without time zone
) PARTITION BY HASH(userid);

Create the first level partition as follows:

CREATE TABLE userinfo_p0 PARTITION OF userinfo FOR VALUES WITH(MODULUS 4, REMAINDER 0) PARTITION BY RANGE(ctime);
CREATE TABLE userinfo_p1 PARTITION OF userinfo FOR VALUES WITH(MODULUS 4, REMAINDER 1);
CREATE TABLE userinfo_p2 PARTITION OF userinfo FOR VALUES WITH(MODULUS 4, REMAINDER 2);
CREATE TABLE userinfo_p3 PARTITION OF userinfo FOR VALUES WITH(MODULUS 4, REMAINDER 3);

Create a second-level partition as follows:

CREATE TABLE userinfo_p0_old PARTITION OF userinfo_p0 FOR VALUES FROM (MINVALUE) TO ('2019-06-01');
CREATE TABLE userinfo_p0_201906 PARTITION OF userinfo_p0 FOR VALUES FROM ('2019-06-01') TO ('2019-07-01');
CREATE TABLE userinfo_p0_201907 PARTITION OF userinfo_p0 FOR VALUES FROM ('2019-07-01') TO ('2019-08-01');

Use the meta command to view partition table information, as follows:

mydb=> \d + userinfo
                                        Partitioned table "pguser.userinfo"
  Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
---------- + -------------------------------- + ------ ----- + ---------- + --------- + ---------- + ---------- -- +-------------
 userid | integer | | | | plain | |
 username | character varying(64) | | | | extended | |
 ctime | timestamp(6) without time zone | | | | plain | |
Partition key: HASH (userid)
Partitions: userinfo_p0 FOR VALUES WITH (modulus 4, remainder 0), PARTITIONED,
            userinfo_p1 FOR VALUES WITH (modulus 4, remainder 1),
            userinfo_p2 FOR VALUES WITH (modulus 4, remainder 2),
            userinfo_p3 FOR VALUES WITH (modulus 4, remainder 3)
                      

Note: Most of the information of the partition table can be viewed above, but the information of the secondary partition is not displayed. The userinfo_p0 line only displays PARTITIONED and does not list the secondary partition information.

If you want to view the secondary partition information, do the following:

mydb=> \d + userinfo_p0
                                       Partitioned table "pguser.userinfo_p0"
  Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
---------- + -------------------------------- + ------ ----- + ---------- + --------- + ---------- + ---------- -- +-------------
 userid | integer | | | | plain | |
 username | character varying(64) | | | | extended | |
 ctime | timestamp(6) without time zone | | | | plain | |
Partition of: userinfo FOR VALUES WITH (modulus 4, remainder 0)
Partition constraint: satisfies_hash_partition('16432'::oid, 4, 0, userid)
Partition key: RANGE (ctime)
Partitions: userinfo_p0_201906 FOR VALUES FROM ('2019-06-01 00:00:00') TO ('2019-07-01 00:00:00'),
            userinfo_p0_201907 FOR VALUES FROM ('2019-07-01 00:00:00') TO ('2019-08-01 00:00:00'),
            userinfo_p0_old FOR VALUES FROM (MINVALUE) TO ('2019-06-01 00:00:00') 

pg_partition_tree function

Use the pg_partition_tree() function to view partition table information, as follows:

mydb=> SELECT * FROM pg_partition_tree('userinfo');
       relid | parentrelid | isleaf | level
-------------------- + ------------- + -------- + ------ -
 userinfo | | f | 0
 userinfo_p0 | userinfo | f | 1
 userinfo_p1 | userinfo | t | 1
 userinfo_p2 | userinfo | t | 1
 userinfo_p3 | userinfo | t | 1
 userinfo_p0_201906 | userinfo_p0 | t | 2
 userinfo_p0_201907 | userinfo_p0 | t | 2
 userinfo_p0_old | userinfo_p0 | t | 2
(8 rows)

Note: The pg_partition_tree() function lists all partitions of the partition table, the upper-level partition, whether it is a leaf node, and the level information of the current partition.

pg_partition_ancestors function

The pg_partition_ancestors function returns the name of the upper-level partition, including the name of the current-level partition, as follows:

mydb=> SELECT pg_partition_ancestors('userinfo_p0');
 pg_partition_ancestors
--------------------------
 userinfo_p0
 userinfo
(2 rows)

pg_partition_root function

The pg_partition_root() function returns the top-level parent table name, as follows:

mydb=> SELECT pg_partition_root('userinfo_p0_201907');
 pg_partition_root
-------------------
 userinfo
(1 row)

Verify data distribution

Finally, verify the userinfo data distribution of the two-dimensional partition table and insert test data, as follows:

INSERT INTO userinfo(userid,username,ctime) SELECT n, n || '_username',now() FROM generate_series(1,8) n;
INSERT INTO userinfo(userid,username,ctime) SELECT n, n || '_username',now() - interval ' 2 months 'FROM generate_series(1,8) n;

Verify the data distribution as follows:

mydb=> \dt + userinfo*
                                  List of relations
 Schema | Name | Type | Owner | Size | Description
-------- + -------------------- + ------------------------ + -------- + ---------------- + -------------
 pguser | userinfo | partitioned table | pguser | 0 bytes |
 pguser | userinfo_p0 | partitioned table | pguser | 0 bytes |
 pguser | userinfo_p0_201906 | table | pguser | 8192 bytes |
 pguser | userinfo_p0_201907 | table | pguser | 0 bytes |
 pguser | userinfo_p0_old | table | pguser | 8192 bytes |
 pguser | userinfo_p1 | table | pguser | 8192 bytes |
 pguser | userinfo_p2 | table | pguser | 8192 bytes |
 pguser | userinfo_p3 | table | pguser | 8192 bytes |
(8 rows)

Based on the table size, it is initially determined that only the underlying partition stores data.

View the distribution of secondary partition data, as follows:

mydb=> SELECT * FROM userinfo_p0;
 userid | username | ctime
-------- + ------------ + ----------------------------
      1 | 1_username | 2019-05-16 09:36:18.83122
      1 | 1_username | 2019-07-16 09:36:18.825426
(2 rows)

View the three-level partition data distribution, as follows:

mydb=> SELECT * FROM userinfo_p0_201907;
 userid | username | ctime
-------- + ------------ + ----------------------------
      1 | 1_username | 2019-07-16 09:36:18.825426
(1 row)

mydb=> SELECT * FROM userinfo_p0_201906;
 userid | username | ctime
-------- + ---------- + -------
(0 rows)

mydb=> SELECT * FROM userinfo_p0_old;
 userid | username | ctime
-------- + ------------ + --------------------------
      1 | 1_username | 2019-05-16 09:36:18.83122

Summary

For one-dimensional partitioned tables, the meta-commands provided by PostgreSQL are enough to view the complete information of the partition, but for multi-dimensional partitioned tables, the meta-commands cannot view detailed partition information. The partition functions provided by PostgreSQL 12 can easily do this.

Although two-dimensional partitioned tables are not widely used, the partitioned table function provides another way to query partitioned tables.

Reference

  • Waiting for PostgreSQL 12 – Add pg_partition_tree to display information about partitions
  • Postgres 12 highlight – Functions for partitions