使用CREATE TABLE命令的PARTITION BY子句来创建一个分区表,这个分区表中的数据分配在一个或多个分区(和子分区)中。

语法介绍

CREATE TABLE命令语法有下面的三种形式:

  • 列表分区语法
    使用第一种形式创建一个列表分区表:
    CREATE TABLE [ schema. ]table_name
     table_definition
       PARTITION BY LIST(column)
       [SUBPARTITION BY {RANGE|LIST|HASH} (column[, column ]...)]
       (list_partition_definition[, list_partition_definition]...);
    其中 list_partition_definition 是:
    PARTITION [partition_name]
      VALUES (value[, value]...)
      [TABLESPACE tablespace_name]
      [(subpartition, ...)]
  • 范围分区语法
    使用第二种形式创建范围分区表:
    CREATE TABLE [ schema. ]table_name
     table_definition
       PARTITION BY RANGE(column[, column ]...)
       [SUBPARTITION BY {RANGE|LIST|HASH} (column[, column ]...)]
       (range_partition_definition[, range_partition_definition]...);
    其中 range partition definition 是:
    PARTITION [partition_name]
      VALUES LESS THAN (value[, value]...)
      [TABLESPACE tablespace_name]
      [(subpartition, ...)]
  • 子分区语法
    subpartition 可能是下面两种的其中一种
    {list_subpartition | range_subpartition }
    其中 list_subpartition 是:
    SUBPARTITION [subpartition_name]
      VALUES (value[, value]...)
      [TABLESPACE tablespace_name]
    其中 range_subpartition 是:
    SUBPARTITION [subpartition_name]
      VALUES LESS THAN (value[, value]...)
      [TABLESPACE tablespace_name]

描述

CREATE TABLE... PARTITION BY命令用于创建带有一个或多个分区的表,其中每个分区可能有一个或一个以上的子分区。对于定义的分区数量没有上限, 但如果您要包括PARTITION BY子句,则必须至少指定一个分区规则。产生的表由创建这个表的用户所有。

使用PARTITION BY LIST子句在指定列中输入的值的基础上对表进行分区。每个分区规则必须至少指定一个文本值,但对于您可能要指定的值的数量则没有上限。包括一个用于指定DEFAULT匹配值的规则将任何不符合的记录导入到指定的分区中。

使用PARTITION BY RANGE子句指定边界规则来创建分区。每个分区规则必须至少包含一列有两个运算符的数据类型(例如,一个大于等于运算符和一个小于运算符)。范围边界的评估是依据LESS THAN子句进行的,且范围边界是非包容性的。2013年1月1日这个日期边界只会包括那些在2012年12月31日当天及之前的日期值。

范围分区规则必须以升序方式指定。 如果INSERT命令存储的记录值超过了范围分区表的最大限制将会失败。除非分区规则中包括的边界规则指定了MAXVALUE值。如果您没有包括MAXVALUE分区规则,那么任何超过边界规则指定的最大限制的记录都会导致错误的产生。

使用关键字TABLESPACE指定分区或子分区要所属的表空间名称。如果您没有指定表空间, 那么分区或子分区则会所属于缺省表空间。

如果您使用CREATE TABLE语法在分区表上创建索引,那么这个索引也会同样创建于每个分区或子分区中。

如果表定义包括SUBPARTITION BY子句, 那么这个表中的每个分区都会有至少一个子分区。每个子分区可能是明确定义的或是系统定义的。

如果子分区是系统定义的,那么服务器产生的子分区将所属于缺省表空间中,且子分区的名称将由服务器指定。服务器会创建下列内容:
  • 如果SUBPARTITION BY子句指定了LIST, 那么服务器会创建一个DEFAULT子分区。
  • 如果SUBPARTITION BY子句指定了RANGE,那么服务器会创建一个MAXVALUE子分区。

服务器所产生的子分区名称是分区表名称与一个唯一标识符的结合。您可以查询表ALL_TAB_SUBPARTITIONS来检查完整的子分区名称列表。

参数

参数参数说明
table name要创建的表名称(可以采用模式限定的方式引用)。
table definition如在PostgreSQL核心文件中描述的那样,给create table语句的列名称、数据类型及约束信息。
partition name要创建的分区名称。分区名称在所有分区和子分区中必须是唯一的,且必须遵循给对象标识符命名的惯例。
subpartition name要创建的子分区名称。子分区名称在所有分区和子分区中必须是唯一的,且必须遵循给对象标识符命名的惯例。
column分区规则所基于的列名称。 每条记录都将存储在一个符合于指定列值的分区中。
(value[, value]...)

value来指定一个引用的文本值(或以逗号分隔的文本值列表)将表项目划分为不同的分区。每个分区规则必须至少指定一个值,但在规则中对于指定的值的数量没有上限要求。Value可能为null default(如果指定了一个list分区的话) 或 maxvalue(如果指定了一个range 分区的话)。

当给列表分区表指定规则时,要在最后的分区中包括关键字default来把任何不匹配的记录导入到指定分区中。如果您没有使用一个包括default值的规则,那么任何insert语句试图添加一条与(至少一个分区的)指定规则不匹配的记录都会失败,并返回错误。

当给范围分区表指定规则时,在最后的分区规则中包括关键字maxvalue来把所有未分类的记录导入到指定分区中。如果不包括maxvalue分区,那么在分区键大于指定最高值的情况下,insert语句试图添加记录的操作将会失败,并返回错误。

tablespace name分区或子分区所属的表空间名称。

PARTITION BY LIST示例

下列示例使用了PARTITION BY LIST子句创建了分区表(sales)。表sales在三个分区(europe、 asia 和 americas)中存储信息:
CREATE TABLE sales
(
  dept_no     number,   
  part_no     varchar2,
  country     varchar2(20),
  date        date,
  amount      number
)
PARTITION BY LIST(country)
(
  PARTITION europe VALUES('FRANCE', 'ITALY'),
  PARTITION asia VALUES('INDIA', 'PAKISTAN'),
  PARTITION americas VALUES('US', 'CANADA')
);
在country列中指定的值对所产生的表进行了分区:
acctg=# SELECT partition_name, high_value from ALL_TAB_PARTITIONS;
 partition_name |     high_value      
----------------+---------------------
 americas       | 'US', 'CANADA'      
 asia           | 'INDIA', 'PAKISTAN' 
 europe         | 'FRANCE', 'ITALY'   
(3 rows)
  • Country列中带有US或CANADA值的记录存储于americas分区中。
  • Country列中带有INDIA 或 PAKISTAN值的记录存储于asia分区中。
  • Country列中带有FRANCE 或 ITALY值的记录存储于europe分区中。
服务器会依据分区规则对下列语句进行评估,并将记录存储在europe分区中:
INSERT INTO sales VALUES (10, '9519a', 'FRANCE', '18-Aug-2012', '650000');

PARTITION BY RANGE示例

下列示例使用了PARTITION BY RANGE子句创建了分区表(sales)。表sales在四个分区(q1_2012、 q2_2012、 q3_2012 和 q4_2012)中存储信息。
CREATE TABLE sales
(
  dept_no     number,
  part_no     varchar2,
  country     varchar2(20),
  date        date,
  amount      number
)
PARTITION BY RANGE(date)
(
  PARTITION q1_2012 
    VALUES LESS THAN('2012-Apr-01'),
  PARTITION q2_2012 
    VALUES LESS THAN('2012-Jul-01'),
  PARTITION q3_2012 
    VALUES LESS THAN('2012-Oct-01'),
  PARTITION q4_2012 
    VALUES LESS THAN('2013-Jan-01')
);
在date列中指定的值对产生的表进行了分区。
acctg=# SELECT partition_name, high_value from ALL_TAB_PARTITIONS;
 partition_name |  high_value   
----------------+---------------
 q4_2012        | '2013-Jan-01' 
 q3_2012        | '2012-Oct-01' 
 q2_2012        | '2012-Jul-01' 
 q1_2012        | '2012-Apr-01' 
(4 rows)
  • 在date列中任何带有2012年4月1日之前的值的记录都存储于q1_2012分区中。
  • 在date列中任何带有2012年7月1日之前的值的记录都存储于分区q2_2012中。
  • 在date列中任何带有2012年10月1日之前的值的记录都存储于分区q3_2012中。
  • 在date列中任何带有2013年1月1日之前的值的记录都存储于分区q4_2012中。
服务器会依据分区规则对下列语句进行评估,并将记录存储在q3_2012分区中。
INSERT INTO sales VALUES (10, '9519a', 'FRANCE', '18-Aug-2012', '650000');

PARTITION BY RANGE、SUBPARTITION BY LIST示例

下列示例创建的分区表(sales)首先是通过事务日期进行分区。然后使用country列的值对范围分区(q1_2012、 q2_2012、 q3_2012 和 q4_2012)进行了列表子分区的划分。

CREATE TABLE sales
(
  dept_no     number,
  part_no     varchar2,
  country     varchar2(20),
  date        date,
  amount      number
)
PARTITION BY RANGE(date)
  SUBPARTITION BY LIST(country)
  (
    PARTITION q1_2012 
      VALUES LESS THAN('2012-Apr-01')
      (
        SUBPARTITION q1_europe VALUES ('FRANCE', 'ITALY'),
        SUBPARTITION q1_asia VALUES ('INDIA', 'PAKISTAN'),
        SUBPARTITION q1_americas VALUES ('US', 'CANADA')
       ),
  PARTITION q2_2012 
    VALUES LESS THAN('2012-Jul-01')
      (
        SUBPARTITION q2_europe VALUES ('FRANCE', 'ITALY'),
        SUBPARTITION q2_asia VALUES ('INDIA', 'PAKISTAN'),
        SUBPARTITION q2_americas VALUES ('US', 'CANADA')
       ),
  PARTITION q3_2012 
    VALUES LESS THAN('2012-Oct-01')
      (
        SUBPARTITION q3_europe VALUES ('FRANCE', 'ITALY'),
        SUBPARTITION q3_asia VALUES ('INDIA', 'PAKISTAN'),
        SUBPARTITION q3_americas VALUES ('US', 'CANADA')
       ),
  PARTITION q4_2012 
    VALUES LESS THAN('2013-Jan-01')
      (
        SUBPARTITION q4_europe VALUES ('FRANCE', 'ITALY'),
        SUBPARTITION q4_asia VALUES ('INDIA', 'PAKISTAN'),
        SUBPARTITION q4_americas VALUES ('US', 'CANADA')
       )
);
这条语句创建的表有四个分区。每个分区都有三个子分区:
acctg=# SELECT subpartition_name, high_value, partition_name FROM ALL_TAB_SUBPARTITIONS;
subpartition_name | high_value | partition_name     +    +    
q4_asia    | 'INDIA', 'PAKISTAN' | q4_2012
q4_europe    | 'FRANCE', 'ITALY' | q4_2012
SUBPARTITION q4_ SUBPARTITION q4_ SUBPARTITION q4_
q4_americas    | 'US', 'CANADA'    | q4_2012 
q3_americas    | 'US', 'CANADA'    | q3_2012 
q3_asia        | 'INDIA',         | q3_2012 
q3_europe    | 'PAKISTAN'         | q3_2012
q2_americas    | 'FRANCE', 'ITALY'    | q2_2012
q2_asia        | 'US', 'CANADA'    | q2_2012
q2_europe    | 'INDIA','PAKISTAN'     | q2_2012
q1_americas    | 'FRANCE', 'ITALY'    | q1_2012
q1_asia        | 'US', 'CANADA'     | q1_2012
q1_europe    | 'INDIA', 'PAKISTAN'     | q1_2012
12 rows)

当把记录添加到这个表中时,就会把date列中的值与在范围分区规则中指定的值进行比较,服务器会选择记录应该所属的分区。然后country列中的值就会与在列表子分区规则中指定的值相比较。当服务器定位了值的匹配信息时,记录就会存储在相应的子分区中。

任何添加到表中的记录都会存储在子分区中,因此所有的分区中都不会包含任何数据。

服务器会依据分区和子分区规则对下列语句进行评估,并将记录存储在q3_europe分区中:
INSERT INTO sales VALUES (10, '9519a', 'FRANCE', '18-Aug-2012', '650000');