The classic partitioning syntax reflects the partitioning syntax of prior versions of VMware Greenplum. It is most appropriate for a homogenous partitioned table, where all partitions are at the same leaf level and have the same partition rule.
If you are already familiar with the classic partitioning syntax, refer to About Changes to Table Partitioning in Greenplum 7 for information about syntax and behavior changes introduced in version 7.
This section includes several examples that use the classic syntax for creating a partitioned table.
A date-range partitioned table uses a single date type column as the partition key column.
With the classic syntax, you can instruct Greenplum Database to automatically generate partitions by providing a START
value, an END
value, and an EVERY
clause that defines the partition increment value. By default, START
values are always inclusive and END
values are always exclusive. For example, to create a daily-partitioned table named `sales:
CREATE TABLE sales (id int, date date, amt decimal(10,2))
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
( START (date '2022-01-01') INCLUSIVE
END (date '2023-01-01') EXCLUSIVE
EVERY (INTERVAL '1 day') );
You can also declare and name each partition individually. For example:
CREATE TABLE sales (id int, date date, amt decimal(10,2))
DISTRIBUTED BY (id)
PARTITION BY RANGE (date)
( PARTITION Jan22 START (date '2022-01-01') INCLUSIVE ,
PARTITION Feb22 START (date '2022-02-01') INCLUSIVE ,
PARTITION Mar22 START (date '2022-03-01') INCLUSIVE ,
PARTITION Apr22 START (date '2022-04-01') INCLUSIVE ,
PARTITION May22 START (date '2022-05-01') INCLUSIVE ,
PARTITION Jun22 START (date '2022-06-01') INCLUSIVE ,
PARTITION Jul22 START (date '2022-07-01') INCLUSIVE ,
PARTITION Aug22 START (date '2022-08-01') INCLUSIVE ,
PARTITION Sep22 START (date '2022-09-01') INCLUSIVE ,
PARTITION Oct22 START (date '2022-10-01') INCLUSIVE ,
PARTITION Nov22 START (date '2022-11-01') INCLUSIVE ,
PARTITION Dec22 START (date '2022-12-01') INCLUSIVE
END (date '2023-01-01') EXCLUSIVE );
You need not declare an END
value for each partition, only the last one. In this example, Jan22
ends where Feb22
starts.
A numeric-range partitioned table uses a single numeric type column as the partition key column.
For example, create a table named nrank
that is numeric-range partitioned on the int
column year
:
CREATE TABLE nrank (id int, rank int, year int, color char(1), count int)
DISTRIBUTED BY (id)
PARTITION BY RANGE (year)
( START (2012) END (2022) EVERY (1),
DEFAULT PARTITION extra );
A list partitioned table can use any data type column that allows equality comparisons as its partition key column. With the classic syntax, a list partition can have a multi-column (composite) partition key. For list partitions, you must declare a partition for every list value. For example:
CREATE TABLE rank (id int, rank int, year int, color char(1), count int )
DISTRIBUTED BY (id)
PARTITION BY LIST (color)
( PARTITION red VALUES ('r'),
PARTITION blue VALUES ('b'),
PARTITION green VALUES ('g'),
DEFAULT PARTITION other );
NoteWhile the Postgres-based planner allows list partitions with multi-column (composite) partition keys, the Greenplum query optimizer (GPORCA) does not support this.
You can create a multi-level partition design with sub-partitions of partitions. Using a sub-partition template ensures that every partition has the same sub-partition design, including partitions that you add later. For example, the following SQL creates the two-level partition design shown in Example Multi-Level Partition Design:
CREATE TABLE sales (trans_id int, date date, amount decimal(9,2), region text)
DISTRIBUTED BY (trans_id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
( SUBPARTITION usa VALUES ('usa'),
SUBPARTITION asia VALUES ('asia'),
SUBPARTITION europe VALUES ('europe'),
DEFAULT SUBPARTITION other_regions)
(START (date '2011-01-01') INCLUSIVE
END (date '2012-01-01') EXCLUSIVE
EVERY (INTERVAL '1 month'),
DEFAULT PARTITION outlying_dates );
The following example shows a three-level partition design where the sales
table is partitioned by year
, then month
, then region
. The SUBPARTITION TEMPLATE
clauses ensure that each yearly partition has the same sub-partition structure. The example declares a DEFAULT
partition at each level of the hierarchy.
CREATE TABLE p3_sales (id int, year int, month int, day int,
region text)
DISTRIBUTED BY (id)
PARTITION BY RANGE (year)
SUBPARTITION BY RANGE (month)
SUBPARTITION TEMPLATE (
START (1) END (13) EVERY (1),
DEFAULT SUBPARTITION other_months )
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE (
SUBPARTITION usa VALUES ('usa'),
SUBPARTITION europe VALUES ('europe'),
SUBPARTITION asia VALUES ('asia'),
DEFAULT SUBPARTITION other_regions )
( START (2002) END (2012) EVERY (1),
DEFAULT PARTITION outlying_years );
CAUTION: When you create multi-level partitions on ranges, it is easy to create a large number of sub-partitions, some containing little or no data. This can add many entries to the system tables, which increases the time and memory required to optimize and run queries. Increase the range interval or choose a different partitioning strategy to reduce the number of sub-partitions created.
With classic syntax, tables can be partitioned only at creation. If you have a table that you want to partition, you must create a partitioned table, load the data from the original table into the new table, drop the original table, and rename the partitioned table with the original table's name. You must also re-grant any table permissions. For example:
CREATE TABLE sales2 (LIKE sales)
PARTITION BY RANGE (date)
( START (date 2016-01-01') INCLUSIVE
END (date '2017-01-01') EXCLUSIVE
EVERY (INTERVAL '1 month') );
INSERT INTO sales2 SELECT * FROM sales;
DROP TABLE sales;
ALTER TABLE sales2 RENAME TO sales;
GRANT ALL PRIVILEGES ON sales TO admin;
GRANT SELECT ON sales TO guest;
NoteThe
LIKE
clause does not copy over partition structures when creating a new table.
To maintain a partitioned table that you created with the classic syntax, use the ALTER TABLE
command against the top-level root partitioned table. The most common scenario is to drop old partitions and add new ones to maintain a rolling window of data in a range partition design. You can convert (exchange) older partitions to the append-optimized compressed storage format to save space. If you have a default partition in your partition design, you add a partition by splitting the default partition.
ImportantWhen defining and altering partition designs, use the given partition name, not the table object name. The given partition name is the
relid
column returned by thepg_partition_tree()
function. Although you can query and load any table (including partitioned tables) directly using SQL commands, you can only modify the structure of a partitioned table that you create with classic partitioning syntax using theALTER TABLE ... PARTITION
clauses.
Partitions are not required to have names. If a partition does not have a name, use the following expression to identify a partition: PARTITION FOR (value)
.
For a multi-level partitioned table, you identify a specific partition to change with ALTER PARTITION
clauses. For each partition level in the table hierarchy that is above the target partition, specify the partition that is related to the target partition in an ALTER PARTITION
clause. For example, if you have a partitioned table that consists of three levels, year, quarter, and region, this ALTER TABLE
command exchanges a leaf partition region
with the table region_new
.
ALTER TABLE sales ALTER PARTITION year_1 ALTER PARTITION quarter_4 EXCHANGE PARTITION region WITH TABLE region_new ;
The two ALTER PARTITION
clauses identify which region
partition to exchange. Both clauses are required to identify the specific leaf partition to exchange.
You can add a partition to a partition design with the ALTER TABLE
command. If the original partition design included sub-partitions defined by a sub-partition template, the newly added partition is sub-partitioned according to that template. For example:
ALTER TABLE sales ADD PARTITION
START (date '2017-02-01') INCLUSIVE
END (date '2017-03-01') EXCLUSIVE;
If you did not use a sub-partition template when you created the table, you define sub-partitions when adding a partition:
ALTER TABLE sales ADD PARTITION
START (date '2017-02-01') INCLUSIVE
END (date '2017-03-01') EXCLUSIVE
( SUBPARTITION usa VALUES ('usa'),
SUBPARTITION asia VALUES ('asia'),
SUBPARTITION europe VALUES ('europe') );
When you add a sub-partition to an existing partition, you can specify the partition to alter. For example:
ALTER TABLE sales ALTER PARTITION FOR ('2017-02-07'::date)
ADD PARTITION africa VALUES ('africa');
NoteYou cannot add a partition to a partition design that has a default partition. You must split the default partition to add a partition. See Splitting a Partition.
Sub-partition tables created with the classic syntax use the following naming convention. Partitioned subtable names are subject to uniqueness requirements and length limitations.
<parentname>_<level>_prt_<partition_name>
For example:
sales_1_prt_jan16
For auto-generated range partitions, where a number is assigned when no name is given:
sales_1_prt_1
To rename a partitioned child table, rename the top-level parent table. The <parentname>
changes in the table names of all associated child tables. For example, the following command:
ALTER TABLE sales RENAME TO globalsales;
Changes the associated table names:
globalsales_1_prt_1
You can change the name of a partition to make it easier to identify. For example:
ALTER TABLE sales RENAME PARTITION FOR ('2016-01-01') TO jan16;
Changes the associated table name as follows:
sales_1_prt_jan16
When altering partitioned tables with the ALTER TABLE
command, always refer to the tables by their partition name (jan16
) and not their full table name (sales_1_prt_jan16
).
NoteThe table name cannot be a partition name in an
ALTER TABLE
statement. For example,ALTER TABLE sales...
is correct,ALTER TABLE sales_1_part_jan16...
is not allowed.
You can add a default partition to a partition design with the ALTER TABLE
command.
ALTER TABLE sales ADD DEFAULT PARTITION other;
If your partition design is multi-level, each level in the hierarchy must have a default partition. For example:
ALTER TABLE sales ALTER PARTITION FOR ('2017-03-01'::date) ADD DEFAULT PARTITION other;
ALTER TABLE sales ALTER PARTITION FOR ('2017-05-01'::date) ADD DEFAULT PARTITION other;
ALTER TABLE sales ALTER PARTITION FOR (2017-07-01::date) ADD DEFAULT PARTITION other;
If incoming data does not match a partition's constraint and there is no default partition, the data is rejected. Default partitions ensure that incoming data that does not match a partition is inserted into the default partition.
You can drop a partition from your partition design using the ALTER TABLE
command. When you drop a partition that has sub-partitions, the sub-partitions (and all data in them) are automatically dropped as well. For range partitions, it is common to drop the older partitions from the range as old data is rolled out of the data warehouse. For example:
ALTER TABLE sales DROP PARTITION FOR ('2017-03-01'::date);
You can truncate a partition using the ALTER TABLE
command. When you truncate a partition that has sub-partitions, the sub-partitions are automatically truncated as well.
ALTER TABLE sales TRUNCATE PARTITION FOR ('2017-02-01'::date);
You can exchange a partition using the ALTER TABLE
command. Exchanging a partition swaps one table in place of an existing partition. You can exchange partitions only at the lowest level of your partition hierarchy (only partitions that contain data can be exchanged).
Internally, Greenplum Database converts an ALTER TABLE ... EXCHANGE PARTITION
command into modern syntax DETACH PARTITION
and ATTACH PARTITION
commands (with some name swapping).
You cannot exchange a partition with a replicated table. Exchanging a partition with a partitioned table or a child partition of a partitioned table is not supported.
NoteGreenplum Database always validates the data against the partition constraint. You must ensure that the data in the table that you are attaching is valid against the constraints on the partition.
Splitting a partition divides a partition into two partitions. You can split a partition using the ALTER TABLE
command. You can split partitions only at the lowest level of your partition hierarchy (partitions that contain data). For a multi-level partition, only range partitions can be split, not list partitions. The split value you specify goes into the latter partition.
For example, to split a monthly partition into two with the first partition containing dates January 1-15 and the second partition containing dates January 16-31:
ALTER TABLE sales SPLIT PARTITION FOR ('2017-01-01')
AT ('2017-01-16')
INTO (PARTITION jan171to15, PARTITION jan1716to31);
If your partition design has a default partition, you must split the default partition to add a partition.
When using the INTO
clause, specify the current default partition as the second partition name. For example, to split a default range partition to add a new monthly partition for January 2017:
ALTER TABLE sales SPLIT DEFAULT PARTITION
START ('2017-01-01') INCLUSIVE
END ('2017-02-01') EXCLUSIVE
INTO (PARTITION jan17, default partition);
Use ALTER TABLE ... SET SUBPARTITION TEMPLATE
to modify the sub-partition template of a partitioned table. Partitions added after you set a new sub-partition template have the new partition design. Existing partitions are not modified.
The following example alters the sub-partition template of this partitioned table:
CREATE TABLE sales (trans_id int, date date, amount decimal(9,2), region text)
DISTRIBUTED BY (trans_id)
PARTITION BY RANGE (date)
SUBPARTITION BY LIST (region)
SUBPARTITION TEMPLATE
( SUBPARTITION usa VALUES ('usa'),
SUBPARTITION asia VALUES ('asia'),
SUBPARTITION europe VALUES ('europe'),
DEFAULT SUBPARTITION other_regions )
( START (date '2014-01-01') INCLUSIVE
END (date '2014-04-01') EXCLUSIVE
EVERY (INTERVAL '1 month') );
This ALTER TABLE
command, modifies the sub-partition template.
ALTER TABLE sales SET SUBPARTITION TEMPLATE
( SUBPARTITION usa VALUES ('usa'),
SUBPARTITION asia VALUES ('asia'),
SUBPARTITION europe VALUES ('europe'),
SUBPARTITION africa VALUES ('africa'),
DEFAULT SUBPARTITION regions );
When you add a date-range partition of the table sales, it includes the new regional list sub-partition for Africa. For example, the following command creates the sub-partitions usa
, asia
, europe
, africa
, and a default partition named other
:
ALTER TABLE sales ADD PARTITION "4"
START ('2014-04-01') INCLUSIVE
END ('2014-05-01') EXCLUSIVE;
To view the tables created for the partitioned table sales
, you can use the command \dt sales*
from the psql command line.
To remove a sub-partition template, use SET SUBPARTITION TEMPLATE
with empty parentheses. For example, to clear the sales table sub-partition template:
ALTER TABLE sales SET SUBPARTITION TEMPLATE ();
You can exchange a leaf partition of a partitioned table with a readable external table. The external table data can reside on a host file system, an NFS mount, or a Hadoop file system (HDFS).
For example, if you have a partitioned table that is created with monthly partitions and most of the queries against the table only access the newer data, you can copy the older, less accessed data to external tables and exchange older partitions with the external tables. For queries that only access the newer data, you could create queries that use partition elimination to prevent scanning the older, unneeded partitions.
Exchanging a leaf partition with an external table is not supported if the partitioned table contains a column with a check constraint or a NOT NULL
constraint.
For information about exchanging and altering a leaf partition, see the ALTER TABLE command reference.
For information about limitations of partitioned tables that contain a external table partition, see Limitations of Partitioned Tables.
This is a simple example that exchanges a leaf partition of this partitioned table for an external table. The partitioned table contains data for the years 2010 through 2013.
CREATE TABLE sales (id int, year int, qtr int, day int, region text)
DISTRIBUTED BY (id)
PARTITION BY RANGE (year)
( PARTITION yr START (2010) END (2014) EVERY (1) ) ;
There are four leaf partitions for the partitioned table. Each leaf partition contains the data for a single year. The leaf partition sales_1_prt_yr_1
contains the data for the year 2010. These steps exchange the table sales_1_prt_yr_1
with an external table the uses the gpfdist
protocol:
Ensure that the external table protocol is enabled for the Greenplum Database system.
This example uses the gpfdist
protocol. This command starts the gpfdist
protocol.
$ gpfdist
Create a writable external table.
This CREATE WRITABLE EXTERNAL TABLE
command creates a writable external table with the same columns as the partitioned table.
CREATE WRITABLE EXTERNAL TABLE my_sales_ext ( LIKE sales_1_prt_yr_1 )
LOCATION ( 'gpfdist://gpdb_test/sales_2010' )
FORMAT 'csv'
DISTRIBUTED BY (id) ;
Create a readable external table that reads the data from that destination of the writable external table created in the previous step.
This CREATE EXTERNAL TABLE
create a readable external that uses the same external data as the writable external data.
CREATE EXTERNAL TABLE sales_2010_ext (LIKE sales_1_prt_yr_1)
LOCATION ( 'gpfdist://gpdb_test/sales_2010' )
FORMAT 'csv' ;
Copy the data from the leaf partition into the writable external table.
This INSERT
command copies the data from the leaf partition into the external table.
INSERT INTO my_sales_ext SELECT * FROM sales_1_prt_yr_1;
Exchange the existing leaf partition with the external table.
This ALTER TABLE
command specifies the EXCHANGE PARTITION
clause to switch the readable external table and the leaf partition.
ALTER TABLE sales ALTER PARTITION yr_1
EXCHANGE PARTITION yr_1
WITH TABLE sales_2010_ext WITHOUT VALIDATION;
The external table becomes the leaf partition with the table name sales_1_prt_yr_1
and the old leaf partition becomes the table sales_2010_ext
.
CautionIn order to ensure queries against the partitioned table return the correct results, the external table data must be valid against the constraints on the leaf partition.
Drop the table that was rolled out of the partitioned table.
DROP TABLE sales_2010_ext ;
You can rename the name of the leaf partition to indicate that sales_1_prt_yr_1
is an external table.
This example command changes the partitionname
to yr_1_ext
and the name of the leaf partition to sales_1_prt_yr_1_ext
.
ALTER TABLE sales RENAME PARTITION yr_1 TO yr_1_ext ;