Updated on 2025-05-29 GMT+08:00

Range Partitioning

Range partitioning maps data to partitions based on the partition key value range of each partition. Range partitioning is a common partitioning type in actual production systems. It is usually used in scenarios where data is described by time (date and timestamp).

There are two syntax formats for range partitioning. The following is an example:

  1. VALUES LESS THAN

    If the VALUE LESS THAN clause is used, a range partitioning policy supports a partition key with up to 16 columns.

    • The following is an example of a single-column partition key:
      gaussdb=# CREATE TABLE range_sales
      (
          product_id      INT4 NOT NULL,
          customer_id     INT4 NOT NULL,
          time            DATE,
          channel_id      CHAR(1),
          type_id         INT4,
          quantity_sold   NUMERIC(3),
          amount_sold     NUMERIC(10,2)
      )
      PARTITION BY RANGE (time)
      (
          PARTITION date_202001 VALUES LESS THAN ('2020-02-01'),
          PARTITION date_202002 VALUES LESS THAN ('2020-03-01'),
          PARTITION date_202003 VALUES LESS THAN ('2020-04-01'),
          PARTITION date_202004 VALUES LESS THAN ('2020-05-01')
      );
      
      gaussdb=# DROP TABLE range_sales;

      date_202002 indicates the partition of February 2020, which contains the data of the partition key from February 1, 2020 to February 29, 2020.

      Each partition has a VALUES LESS clause, which is used to specify the upper limit of the partition. When the partition key value of the data is greater than or equal to the upper limit of the current partition, the data will be added to the next partition. Except the first partition, all other partitions have a lower limit implicitly specified by the VALUES LESS clause of the previous partition.

      You can specify the MAXVALUE keyword to define the highest partition. MAXVALUE indicates a virtual infinite value. In terms of sorting rules, its priority is higher than that of any other possible value of the partition key, including null values.

    • The following is an example of a multi-column partition key:
      gaussdb=# CREATE TABLE range_sales_with_multiple_keys
      (
          c1      INT4 NOT NULL,
          c2      INT4 NOT NULL,
          c3      CHAR(1)
      )
      PARTITION BY RANGE (c1,c2)
      (
          PARTITION p1 VALUES LESS THAN (10,10),
          PARTITION p2 VALUES LESS THAN (10,20),
          PARTITION p3 VALUES LESS THAN (20,10)
      );
      gaussdb=# INSERT INTO range_sales_with_multiple_keys VALUES(9,5,'a');
      gaussdb=# INSERT INTO range_sales_with_multiple_keys VALUES(9,20,'a');
      gaussdb=# INSERT INTO range_sales_with_multiple_keys VALUES(9,21,'a');
      gaussdb=# INSERT INTO range_sales_with_multiple_keys VALUES(10,5,'a');
      gaussdb=# INSERT INTO range_sales_with_multiple_keys VALUES(10,15,'a');
      gaussdb=# INSERT INTO range_sales_with_multiple_keys VALUES(10,20,'a');
      gaussdb=# INSERT INTO range_sales_with_multiple_keys VALUES(10,21,'a');
      gaussdb=# INSERT INTO range_sales_with_multiple_keys VALUES(11,5,'a');
      gaussdb=# INSERT INTO range_sales_with_multiple_keys VALUES(11,20,'a');
      gaussdb=# INSERT INTO range_sales_with_multiple_keys VALUES(11,21,'a');
      
      gaussdb=# SELECT * FROM range_sales_with_multiple_keys PARTITION (p1);
       c1 | c2 | c3
      ----+----+----
        9 |  5 | a
        9 | 20 | a
        9 | 21 | a
       10 |  5 | a
      (4 rows)
      
      gaussdb=# SELECT * FROM range_sales_with_multiple_keys PARTITION (p2);
       c1 | c2 | c3
      ----+----+----
       10 | 15 | a
      (1 row)
      
      gaussdb=# SELECT * FROM range_sales_with_multiple_keys PARTITION (p3);
       c1 | c2 | c3
      ----+----+----
       10 | 20 | a
       10 | 21 | a
       11 |  5 | a
       11 | 20 | a
       11 | 21 | a
      (5 rows)
      
      gaussdb=# DROP TABLE range_sales_with_multiple_keys;

      The partitioning rules for multi-column partition keys are as follows:

      1. The comparison starts from the first column.
      2. If the value of the inserted first column is smaller than the boundary value of the current column in the target partition, the values are directly inserted.
      3. If the value of the inserted first column is equal to the boundary of the current column in the target partition, compare the value of the inserted second column with the boundary of the next column in the target partition.
      4. If the value of the inserted first column is greater than the boundary of the current column in the target partition, compare the value with that in the next partition.
  2. START END

    If the START END clause is used, a range partitioning policy supports only a one-column partition key.

    Example:
    -- Create a tablespace.
    gaussdb=# CREATE TABLESPACE startend_tbs1 LOCATION '/home/omm/startend_tbs1';
    gaussdb=# CREATE TABLESPACE startend_tbs2 LOCATION '/home/omm/startend_tbs2';
    gaussdb=# CREATE TABLESPACE startend_tbs3 LOCATION '/home/omm/startend_tbs3';
    gaussdb=# CREATE TABLESPACE startend_tbs4 LOCATION '/home/omm/startend_tbs4';
    -- Create a temporary schema.
    gaussdb=# CREATE SCHEMA tpcds;
    gaussdb=# SET CURRENT_SCHEMA TO tpcds;
    -- Create a partitioned table with the partition key of the integer type.
    gaussdb=# CREATE TABLE tpcds.startend_pt (c1 INT, c2 INT)
    TABLESPACE startend_tbs1
    PARTITION BY RANGE (c2) (
        PARTITION p1 START(1) END(1000) EVERY(200) TABLESPACE startend_tbs2,
        PARTITION p2 END(2000),
        PARTITION p3 START(2000) END(2500) TABLESPACE startend_tbs3,
        PARTITION p4 START(2500),
        PARTITION p5 START(3000) END(5000) EVERY(1000) TABLESPACE startend_tbs4
    )
    ENABLE ROW MOVEMENT;
    
    -- View the information of the partitioned table.
    gaussdb=# SELECT relname, boundaries, spcname FROM pg_partition p JOIN pg_tablespace t ON
        p.reltablespace=t.oid and p.parentid='tpcds.startend_pt'::regclass ORDER BY 1;
    relname | boundaries | spcname
    -------------+------------+---------------
    p1_0 | {1} | startend_tbs2
    p1_1 | {201} | startend_tbs2
    p1_2 | {401} | startend_tbs2
    p1_3 | {601} | startend_tbs2
    p1_4 | {801} | startend_tbs2
    p1_5 | {1000} | startend_tbs2
    p2 | {2000} | startend_tbs1
    p3 | {2500} | startend_tbs3
    p4 | {3000} | startend_tbs1
    p5_1 | {4000} | startend_tbs4
    p5_2 | {5000} | startend_tbs4
    startend_pt | | startend_tbs1
    (12 rows)
    
    -- Drop the table and schema.
    gaussdb=#  DROP TABLE tpcds.startend_pt;
    DROP TABLE
    gaussdb=# DROP SCHEMA tpcds;
    DROP SCHEMA