os: centos 7.4
db: postgresql 12.2

postgresql 12 的分区表已经比较完善。

版本

# cat /etc/centos-release
CentOS Linux release 7.4.1708 (Core) 
# 
# su - postgres
Last login: Thu Mar 19 14:47:45 CST 2020 on pts/0
$ 
$ psql
psql (12.2)
Type "help" for help.

postgres=# select version();
                                                 version                                                 
---------------------------------------------------------------------------------------------------------
 PostgreSQL 12.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
(1 row)

postgres=# show enable_partition_pruning;
 enable_partition_pruning 
--------------------------
 on
(1 row)

postgres=# select name,setting from pg_settings where name like '%partition%';
               name                | setting 
-----------------------------------+---------
 enable_partition_pruning          | on
 enable_partitionwise_aggregate    | off
 enable_partitionwise_join         | off
(3 rows) 

single column hash

single column in the partition key

postgres=# CREATE TABLE orders (
    order_id     bigint not null,
    cust_id      bigint not null,
    status       text
) PARTITION BY HASH (order_id);

CREATE TABLE orders_1 PARTITION OF orders FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE orders_2 PARTITION OF orders FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE orders_3 PARTITION OF orders FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE orders_4 PARTITION OF orders FOR VALUES WITH (MODULUS 4, REMAINDER 3);

postgres=# \d+
                                       List of relations
 Schema |             Name              |       Type        |  Owner   |    Size    | Description 
--------+-------------------------------+-------------------+----------+------------+-------------
 public | orders                        | partitioned table | postgres | 0 bytes    | 
 public | orders_1                      | table             | postgres | 8192 bytes | 
 public | orders_2                      | table             | postgres | 8192 bytes | 
 public | orders_3                      | table             | postgres | 8192 bytes | 
 public | orders_4                      | table             | postgres | 8192 bytes | 
(5 rows)

postgres=# select * from pg_inherits;
 inhrelid | inhparent | inhseqno 
----------+-----------+----------
    16664 |     16661 |        1
    16671 |     16661 |        1
    16677 |     16661 |        1
    16683 |     16661 |        1
(4 rows)

postgres=# insert into orders
select id,
       id,
	   md5(id::text)
  from generate_series(1,100000) as id;

postgres=# \d+
                                        List of relations
 Schema |             Name              |       Type        |  Owner   |    Size    | Description 
--------+-------------------------------+-------------------+----------+------------+-------------
 public | orders                        | partitioned table | postgres | 0 bytes    | 
 public | orders_1                      | table             | postgres | 2112 kB    | 
 public | orders_2                      | table             | postgres | 2096 kB    | 
 public | orders_3                      | table             | postgres | 2096 kB    | 
 public | orders_4                      | table             | postgres | 2088 kB    | 
(5 rows)

postgres=# explain select * from orders where order_id=9;
                        QUERY PLAN                         
-----------------------------------------------------------
 Seq Scan on orders_2  (cost=0.00..570.23 rows=1 width=49)
   Filter: (order_id = 9)
(2 rows)

postgres=# explain select * from orders where order_id in (9,10);
                           QUERY PLAN                            
-----------------------------------------------------------------
 Append  (cost=0.00..1138.81 rows=4 width=49)
   ->  Seq Scan on orders_2  (cost=0.00..570.23 rows=2 width=49)
         Filter: (order_id = ANY ('{9,10}'::bigint[]))
   ->  Seq Scan on orders_4  (cost=0.00..568.56 rows=2 width=49)
         Filter: (order_id = ANY ('{9,10}'::bigint[]))
(5 rows)

postgres=# explain select * from orders where order_id between 199 and 202;
                           QUERY PLAN                            
-----------------------------------------------------------------
 Append  (cost=0.00..2533.04 rows=8 width=49)
   ->  Seq Scan on orders_1  (cost=0.00..636.89 rows=2 width=49)
         Filter: ((order_id >= 199) AND (order_id <= 202))
   ->  Seq Scan on orders_2  (cost=0.00..632.67 rows=2 width=49)
         Filter: ((order_id >= 199) AND (order_id <= 202))
   ->  Seq Scan on orders_3  (cost=0.00..632.57 rows=2 width=49)
         Filter: ((order_id >= 199) AND (order_id <= 202))
   ->  Seq Scan on orders_4  (cost=0.00..630.88 rows=2 width=49)
         Filter: ((order_id >= 199) AND (order_id <= 202))
(9 rows)

multiple columns hash

multiple columns in the partition key

postgres=# CREATE TABLE orders_his (
    order_id     bigint not null,
    cust_id      bigint not null,
    status       text
) PARTITION BY HASH (order_id,cust_id);

CREATE TABLE orders_his_1 PARTITION OF orders_his FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE orders_his_2 PARTITION OF orders_his FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE orders_his_3 PARTITION OF orders_his FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE orders_his_4 PARTITION OF orders_his FOR VALUES WITH (MODULUS 4, REMAINDER 3);

postgres=# \d+
                                       List of relations
 Schema |             Name              |       Type        |  Owner   |    Size    | Description 
--------+-------------------------------+-------------------+----------+------------+-------------
 public | orders_his                    | partitioned table | postgres | 0 bytes    | 
 public | orders_his_1                  | table             | postgres | 8192 bytes | 
 public | orders_his_2                  | table             | postgres | 8192 bytes | 
 public | orders_his_3                  | table             | postgres | 8192 bytes | 
 public | orders_his_4                  | table             | postgres | 8192 bytes | 
(5 rows)

postgres=# select * from pg_inherits;
 inhrelid | inhparent | inhseqno 
----------+-----------+----------
    16696 |     16693 |        1
    16702 |     16693 |        1
    16708 |     16693 |        1
    16714 |     16693 |        1
(4 rows)

postgres=# insert into orders_his
select id,
       id,
	   md5(id::text)
  from generate_series(1,200000) as id;

postgres=# \d+
                                        List of relations
 Schema |             Name              |       Type        |  Owner   |    Size    | Description 
--------+-------------------------------+-------------------+----------+------------+-------------
 public | orders_his                    | partitioned table | postgres | 0 bytes    | 
 public | orders_his_1                  | table             | postgres | 4168 kB    | 
 public | orders_his_2                  | table             | postgres | 4144 kB    | 
 public | orders_his_3                  | table             | postgres | 4160 kB    | 
 public | orders_his_4                  | table             | postgres | 4168 kB    | 
(5 rows)

postgres=# explain select * from orders_his where order_id=9;
                              QUERY PLAN                              
----------------------------------------------------------------------
 Append  (cost=0.00..4564.02 rows=4 width=49)
   ->  Seq Scan on orders_his_1  (cost=0.00..1142.81 rows=1 width=49)
         Filter: (order_id = 9)
   ->  Seq Scan on orders_his_2  (cost=0.00..1136.95 rows=1 width=49)
         Filter: (order_id = 9)
   ->  Seq Scan on orders_his_3  (cost=0.00..1140.99 rows=1 width=49)
         Filter: (order_id = 9)
   ->  Seq Scan on orders_his_4  (cost=0.00..1143.25 rows=1 width=49)
         Filter: (order_id = 9)
(9 rows)

postgres=# explain select * from orders_his where order_id=9 and cust_id=9;
                           QUERY PLAN                           
----------------------------------------------------------------
 Seq Scan on orders_his_2  (cost=0.00..1261.54 rows=1 width=49)
   Filter: ((order_id = 9) AND (cust_id = 9))
(2 rows)

参考:
https://www.postgresql.org/docs/12/sql-createtable.html
https://www.postgresql.org/docs/12/ddl-partitioning.html

更多推荐