Partitioning Options
This section describes the PARTITION BY syntax in detail.
range_partition_spec
RANGE ( column BETWEEN start AND end EACH interval [, OUTSIDE RANGE] [, IS NULL] )
- RANGE
Define a number of partitions based on ranges of values bounded by an interval.
- column
A column that exists in the partitioned table. You can define a maximum of four partition columns per table. You cannot specify multiple partitions on the same column. You cannot use expressions to define partition columns.
- BETWEEN start AND end EACH interval
Specify the endpoints of the range, then specify the interval that marks the boundary between partitions. Use literal values with compatible data types. For example:
between date '2017-01-01' and date '2017-06-30' each interval '1 day'
between timestamp '2010-01-01 00:00:00' and timestamp '2016-12-31 23:59:59' each interval '1 year'
between 1 and 10000 each 1
Make sure that the number of partitions derived from the specification does not exceed 32767. For example, the following range is not allowed:
between 1 and 1000000 each 1
The following range is valid:
between 1 and 1000000 each 100
- OUTSIDE RANGE
Optionally, create two separate partitions specifically for values that fall outside (above or below) the specified range. One of these partitions will contain values below the range, and one will contain values above the range.
For example, the following range specification creates 13 partitions, including two
OUTSIDE RANGE
partitions and anIS NULL
partition:range (range_col between 1 and 10 each 1, outside range, is null)
If you query the
sys.table_partition
view for information about a table that has 13 partitions, you will see results like this:premdb=# select * from sys.table_partition; table_id | n1 | n2 | n3 | n4 | count ----------+----+----+----+----+------- 16422 | 0 | 0 | 0 | 0 | 21 16422 | 1 | 0 | 0 | 0 | 462 16422 | 2 | 0 | 0 | 0 | 462 16422 | 3 | 0 | 0 | 0 | 462 16422 | 4 | 0 | 0 | 0 | 380 16422 | 5 | 0 | 0 | 0 | 380 16422 | 6 | 0 | 0 | 0 | 380 16422 | 7 | 0 | 0 | 0 | 380 16422 | 8 | 0 | 0 | 0 | 380 16422 | 9 | 0 | 0 | 0 | 380 16422 | 10 | 0 | 0 | 0 | 380 16422 | 11 | 0 | 0 | 0 | 510 16422 | 12 | 0 | 0 | 0 | 0 (13 rows)
In this result set:
- Row
n1=0
counts values that fall below the range - Rows
n1=1
throughn1=10
count values in the range - Row
n1=11
counts values that fall above the range - Row
n1=12
counts null values
OUTSIDE RANGE
andIS NULL
can be specified in any order.- Row
- IS NULL
Optionally, create a separate partition that holds any
NULL
values.OUTSIDE RANGE
andIS NULL
can be specified in any order.Note: If the partition column may contain
NULL
values, be sure to specifyIS NULL
, or you will be unable to create the table.
hash_partition_spec
HASH ( column WITH number PARTITIONS [, IS NULL] )
- HASH
Define a number of partitions based on hashing the values in a column.
- column
A column that exists in the partitioned table. You can define a maximum of four partitioned columns per table. You cannot specify multiple partitions on the same column.
- WITH number PARTITIONS
Enter a number between 2 and 32767. If an IS NULL partition is specified, the minimum number is 1 and the maximum number is 32766. For example:
with 300 partitions
- IS NULL
Optionally, create a separate partition that holds any
NULL
values.IS NULL
is optional for hash-partitioned tables, butOUTSIDE RANGE
is not meaningful and not required.Note: If the partition column may contain
NULL
values, be sure to specifyIS NULL
, or you will be unable to create the table.
Supported Data Types
The following table shows which column data types are supported for range partitioning and hash partitioning.
Data Type | Range Partitioning Supported | Hash Partitioning Supported |
---|---|---|
BOOLEAN | No | No |
SMALLINT | Yes | Yes |
INTEGER | Yes | Yes |
BIGINT | Yes | Yes |
DECIMAL | No | No |
REAL | No | No |
DOUBLE PRECISION | No | No |
UUID | No | No |
VARCHAR | No | Yes* |
CHAR | No | Yes |
DATE | Yes | Yes |
TIME | No | Yes |
TIMESTAMP | Yes | Yes |
TIMESTAMPTZ | Yes | Yes |
IPV4, IPV6 | No | Yes |
MACADDR, MACADDR8 | No | Yes |
*You cannot hash partition RANDOMIZED
encryption columns.
General Restrictions on Partitioning Tables
- Up to four columns in a single table can be partitioned.
- The number of partitions produced by a single specification must be no greater than 32767.
- The product of the number of partitions produced by all specifications for the same table must be no greater than 250000. For example, the following table cannot be created:
premdb=# create table hashtable(a int not null, b int not null)
partition by (hash(a with 3000 partitions), hash(b with 1000 partitions));
ERROR: the product of the number of partitions produced by all specifications results in 3000000 partitions, 250000 allowed
- Replicated tables cannot be partitioned.
- Partitioning schemes cannot be altered after a table is created. To change partitioning, you have to re-create the table.
Examples
For example, the following table has two range-based partition columns:
- A DATE column, with the partitions separated by an interval of 1 year within a given date range.
- An INTEGER column, using an interval of 1 for the partitions within a given range of numbers. This column also specifies an optional
OUTSIDE RANGE
partition that captures any values outside of the defined range and an optionalIS NULL
partition that capturesNULL
values.
premdb=# create table newmatchstats(seasonid smallint not null, matchday date, htid smallint, atid smallint, moment varchar(5))
distribute on (seasonid)
partition by (
range (matchday between date '8/1/1992' and date '5/31/2017' each interval '1 year', is null),
range (htid between 2 and 51 each 1, outside range, is null)
);
CREATE TABLE
premdb=# \d newmatchstats
Table "public.newmatchstats"
Column | Type | Modifiers
----------+----------------------+-----------
seasonid | smallint | not null
matchday | date |
htid | smallint |
atid | smallint |
moment | character varying(5) |
Distribution: Hash (seasonid)
Partition columns:
"matchday" RANGE (BETWEEN date '1992-08-01' AND date '2017-05-31' EACH interval '1 year')
"htid" RANGE (BETWEEN 2 AND 51 EACH 1, IS NULL, OUTSIDE RANGE)
The following version of the newmatchstats
table has 100 hash partitions based on values in the matchday
column:
premdb=# create table newmatchstats(seasonid smallint not null, matchday date, htid smallint, atid smallint, moment varchar(5))
distribute on (seasonid)
partition by (hash(matchday with 100 partitions, is null));
CREATE TABLE
premdb=# \d newmatchstats
Table "public.newmatchstats"
Column | Type | Modifiers
----------+----------------------+-----------
seasonid | smallint | not null
matchday | date |
htid | smallint |
atid | smallint |
moment | character varying(5) |
Distribution: Hash (seasonid)
Partition Columns:
"matchday" HASH (WITH 100 PARTITIONS)
premdb=# create table partition_test (c1 int, c2 int) partition by (range (c1 between 1 and 10 each 1, is null, outside range));
CREATE TABLE
premdb=# \d partition_test
Table "public.partition_test"
Column | Type | Modifiers
--------+---------+-----------
c1 | integer |
c2 | integer |
Distribution: Hash (c1)
Partition Columns:
"c1" RANGE (BETWEEN 1 AND 10 EACH 1, IS NULL, OUTSIDE RANGE)
premdb=# insert into partition_test(c1) select seasonid from match;
INSERT 0 8606
premdb=# select * from sys.table_partition;
table_id | n1 | n2 | n3 | n4 | count
----------+----+----+----+----+-------
16422 | 0 | 0 | 0 | 0 | 0
16422 | 1 | 0 | 0 | 0 | 462
16422 | 2 | 0 | 0 | 0 | 462
16422 | 3 | 0 | 0 | 0 | 462
16422 | 4 | 0 | 0 | 0 | 380
16422 | 5 | 0 | 0 | 0 | 380
16422 | 6 | 0 | 0 | 0 | 380
16422 | 7 | 0 | 0 | 0 | 380
16422 | 8 | 0 | 0 | 0 | 380
16422 | 9 | 0 | 0 | 0 | 380
16422 | 10 | 0 | 0 | 0 | 380
16422 | 11 | 0 | 0 | 0 | 4560
16422 | 12 | 0 | 0 | 0 | 0
(13 rows)
Parent topic:CREATE TABLE