Interval范围分区

PolarDB PostgreSQL版(兼容Oracle)支持Interval(间隔)范围分区功能,本文详细介绍了其语法和示例。

简介

PolarDB PostgreSQL版(兼容Oracle)提供了自动创建范围分区的特性,即Interval范围分区,在您创建范围分区表时,可以指定Interval表达式,确定自动分区的范围。当插入的值无法匹配到已有分区时,PolarDB PostgreSQL版(兼容Oracle)将自动为您创建一个分区。

Interval范围分区是范围分区的扩展,它允许数据库在新插入的数据超出现有分区的范围时自动创建新分区。要实现间隔范围分区,请包含INTERVAL子句并指定新分区的范围大小。范围分区的高值(也称为转换点)由范围分区键值确定。数据库会为插入的数据创建新的分区,其值超出了该高值。

如果间隔设置为1个月,并且在当前插入最新分区之后两个月的数据,则仅创建该月的分区,而不创建中间分区。 例如,您可以创建一个间隔范围分区表,间隔为每月,最新分区的范围为2019年1月15日至2019年2月15日。如果您尝试插入2019年5月10日的数据,则所需的分区为4月15日到5月15日被创建,数据将插入到该分区中,跳过2019年2月15日至2019年3月15日和2019年3月15日至2019年4月15日的分区,且不会创建这两个分区。

使用限制

以下限制适用于INTERVAL子句:

  • 区间范围分区仅限于单个分区键,该键必须是数字或日期范围。

  • 必须至少定义一个范围分区。

  • 在复合分区中,间隔范围分区可用于主分区机制,但不支持子分区级别。

  • 不支持索引组织表。

  • 不能在LIST分区表上创建域索引。

  • DEFAULT和MAXVALUE不能为区间范围分区表定义。

  • 不能在分区键列中指定NULL、Not-a-Number或Infinity值。

  • 区间范围分区表达式必须产生常量值并且不能为负值。

  • 间隔范围分区表的分区仅支持按照升序创建。

语法

CREATE TABLE [ schema. ]<table_name>
   <table_definition>
   PARTITION BY RANGE(<column>[, <column> ]...)
   [INTERVAL (<constant> | <expression>)]
   [SUBPARTITION BY {RANGE|LIST|HASH} (<column>[, <column> ]...)]
   (<range_partition_definition>[, <range_partition_definition>]...)
   [ENABLE ROW MOVEMENT];
WHERE range_partition_definition IS:
      PARTITION [<partition_name>]
        VALUES LESS THAN (<value>[, <value>]...)
        [TABLESPACE <tablespace_name>]
        [(<subpartition>, ...)]

INTERVAL参数仅支持设置数字和时间间隔:

  • 数字

    相近的10个数字进入同一个分区,示例如下:

    INTERVAL (10)
  • 时间间隔

    • 按年设置自动分区,示例如下:

      INTERVAL (NUMTOYMINTERVAL(1,'year'))
    • 按月设置自动分区,示例如下:

      INTERVAL (NUMTOYMINTERVAL(1,'month'))
    • 按日设置自动分区,示例如下:

      INTERVAL (NUMTODSINTERVAL(1,'day'))
    • 按周设置自动分区,示例如下:

      INTERVAL (NUMTODSINTERVAL(7,'day'))

关于其他参数的介绍,请参见CREATE TABLE...PARTITION BY

示例

本示例展示了按sold_month列上的时间间隔分区的sales表。创建范围分区是为了建立一个转换点,在转换点之外创建新的分区。

在数据库中创建一个新的Interval范围分区,并将数据添加到一个表中。

CREATE TABLE sales
(
  prod_id           int,
  prod_quantity     int,
  sold_month        date
)
PARTITION BY RANGE(sold_month)
INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
(
  PARTITION p1
    VALUES LESS THAN('15-JAN-2019'),
  PARTITION p2
    VALUES LESS THAN('15-FEB-2019')
);

------查询ALL_TAB_PARTITIONS视图
SELECT partition_name, high_value from ALL_TAB_PARTITIONS;
 partition_name |      high_value
----------------+----------------------
 P1             | '15-JAN-19 00:00:00'
 P2             | '15-FEB-19 00:00:00'
(2 rows)

-----向超过范围分区的高值的sales表中插入数据
INSERT INTO sales VALUES (1,200,'10-MAY-2019');
INSERT 0 1

------成功插入数据,系统将生成一个Interval范围分区名称,该名称因每个会话而不同
SELECT partition_name, high_value FROM ALL_TAB_PARTITIONS;
 partition_name |      high_value
----------------+----------------------
 P1             | '15-JAN-19 00:00:00'
 P2             | '15-FEB-19 00:00:00'
 SYS916340103   | '15-MAY-19 00:00:00'
(3 rows)

范围分区和Interval范围分区互转示例

范围分区转换为Interval范围分区

ALTER TABLE...SET INTERVAL命令可将现有的范围分区表转换为Interval范围分区表。

设置范围或时间间隔后,数据库会自动创建一个指定范围或时间间隔的新分区,并将数据插入到新分区中。

语法如下:

ALTER TABLE <table_name> SET INTERVAL (<constant> | <expression>);

Interval范围分区转换为范围分区

SET INTERVAL()命令用于禁用Interval范围分区。禁用后,数据库会将Interval范围分区表转换为范围分区表,并将Interval范围分区的范围或时间间隔设置为范围分区的范围或时间间隔。

语法如下:

ALTER TABLE <table_name> SET INTERVAL ();

示例

以下示例会将表sales从范围分区转换为Interval范围分区,并在分区表中插入数据。

------创建范围分区表sales
CREATE TABLE sales
(
  prod_id           int,
  prod_quantity     int,
  sold_month        date
)
PARTITION BY RANGE(sold_month)
(
  PARTITION p1
    VALUES LESS THAN('15-JAN-2019'),
  PARTITION p2
    VALUES LESS THAN('15-FEB-2019')
);

------查询ALL_TAB_PARTITIONS视图
SELECT partition_name, high_value FROM ALL_TAB_PARTITIONS;
 partition_name |      high_value
----------------+----------------------
 P1             | FOR VALUES FROM ('15-JAN-19 00:00:00') TO ('15-FEB-19 00:00:00')
 P2             | FOR VALUES FROM (MINVALUE) TO ('15-JAN-19 00:00:00')
(2 rows)

------将范围分区表转换为Interval范围分区表
ALTER TABLE sales SET INTERVAL (NUMTOYMINTERVAL(1, 'MONTH'));

-----插入超过范围分区的数据
INSERT INTO sales VALUES (1,100,'05-APR-2019');
INSERT 0 1

SELECT partition_name, high_value FROM ALL_TAB_PARTITIONS;
 partition_name |      high_value
----------------+----------------------
 SYS596430103   | FOR VALUES FROM ('15-MAR-19 00:00:00') TO ('15-APR-19 00:00:00')
 P1             | FOR VALUES FROM ('15-JAN-19 00:00:00') TO ('15-FEB-19 00:00:00')
 P2             | FOR VALUES FROM (MINVALUE) TO ('15-JAN-19 00:00:00')
(3 rows)