CREATE TABLE

定义一个新表。

概要

CREATE [ [GLOBAL | LOCAL] {TEMPORARY | TEMP } | UNLOGGED] TABLE [IF NOT EXISTS]
    table_name (
    { column_name data_type [ COLLATE collation ] [column_constraint [ ... ] ]
[ ENCODING ( storage_directive [, ...] ) ]
    | table_constraint
    | LIKE source_table [ like_option ... ] }
    | [ column_reference_storage_directive [, ...]
    [, ... ]
] )
[ INHERITS ( parent_table [, ... ] ) ]
[ USING { MARS2 | MARS3} ]
[ WITH ( storage_parameter [=value] [, ... ] ) ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]
[ DISTRIBUTED BY (column [opclass], [ ... ] ) 
       | DISTRIBUTED RANDOMLY | DISTRIBUTED REPLICATED ]

{ --partitioned table using SUBPARTITION TEMPLATE
[ PARTITION BY partition_type (column) 
  {  [ SUBPARTITION BY partition_type (column1) 
       SUBPARTITION TEMPLATE ( template_spec ) ]
          [ SUBPARTITION BY partition_type (column2) 
            SUBPARTITION TEMPLATE ( template_spec ) ]
              [...]  }
  ( partition_spec ) ]
} |

{ -- partitioned table without SUBPARTITION TEMPLATE
[ PARTITION BY partition_type (column)
   [ SUBPARTITION BY partition_type (column1) ]
      [ SUBPARTITION BY partition_type (column2) ]
         [...]
  ( partition_spec
     [ ( subpartition_spec_column1
          [ ( subpartition_spec_column2
               [...] ) ] ) ],
  [ partition_spec
     [ ( subpartition_spec_column1
        [ ( subpartition_spec_column2
             [...] ) ] ) ], ]
    [...]
  ) ]
}

CREATE [ [GLOBAL | LOCAL] {TEMPORARY | TEMP} | UNLOGGED ] TABLE [IF NOT EXISTS] 
   table_name
    OF type_name [ (
  { column_name WITH OPTIONS [ column_constraint [ ... ] ]
    | table_constraint } 
    [, ... ]
) ]
[ WITH ( storage_parameter [=value] [, ... ] ) ]
[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
[ TABLESPACE tablespace_name ]

其中 column_constraint 是:

[ CONSTRAINT constraint_name]
{ NOT NULL
  | NULL
  | CHECK ( expression ) [ NO INHERIT ]
  | DEFAULT default_expr
  | UNIQUE index_parameters
  | PRIMARY KEY index_parameters
  | REFERENCES reftable [ ( refcolumn ) ] 
      [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]  
      [ ON DELETE key_action ] [ ON UPDATE key_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

table_constraint 是:

[ CONSTRAINT constraint_name ]
{ CHECK ( expression ) [ NO INHERIT ]
  | UNIQUE ( column_name [, ... ] ) index_parameters
  | PRIMARY KEY ( column_name [, ... ] ) index_parameters
  | FOREIGN KEY ( column_name [, ... ] ) 
      REFERENCES reftable [ ( refcolumn [, ... ] ) ]
      [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] 
      [ ON DELETE key_action ] [ ON UPDATE key_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

like_option 是:

{INCLUDING|EXCLUDING} {DEFAULTS|CONSTRAINTS|INDEXES|STORAGE|COMMENTS|ALL}

UNIQUE 和 PRIMARY KEY 中的 index_parameters 约束为:

[ WITH ( storage_parameter [=value] [, ... ] ) ]
[ USING INDEX TABLESPACE tablespace_name ]

列的 storage_directive 是:

compresstype={ZLIB|ZSTD|QUICKLZ|RLE_TYPE|NONE|MXCUSTOM}
    [compresslevel={0-9}]
    [blocksize={8192-2097152} ]
    // 当 compresstype=MXCUSTOM,需指定具体的 encodechain
    [encodechain={LZ4|ZSTD|DELTADELTA(缩放位数)|DELTAZIGZAG|GORILLA|GORILLA2|FLOATINT|FDS|AUTO}]

表的 storage_parameter 是:

   appendoptimized={TRUE|FALSE}
   blocksize={8192-2097152}
   orientation={COLUMN|ROW}
   checksum={TRUE|FALSE}

   // 以下为编码链相关参数
   compresstype={ZLIB|ZSTD|QUICKLZ|RLE_TYPE|NONE|MXCUSTOM}
   // 当 compresstype=MXCUSTOM,需指定具体的 encodechain
   encodechain={LZ4|ZSTD|DELTADELTA(缩放位数)|DELTAZIGZAG|GORILLA|GORILLA2|FLOATINT|FDS|AUTO}
   /* 当 compresstype=MXCUSTOM,且 encodechain=AUTO 时,支持在表级别指定自适应编码模式:     
    * automode=1 表示压缩率优先,automode=2 表示速度优先 
    */
   automode={1|2}
   compresslevel={0-9}

   fillfactor={10-100}
   [oids=FALSE]

   // 以下为 MARS2 表相关参数
   // 用于控制所有的 MARS2 表,L0 达到多少个 Run 触发合并(v4.5.0 开始支持)
   sortheap_automerge_threshold={10-2048}
   // 用于控制 MARS2 单表 L0 达到多少个Run 触发合并(v4.5.0 开始支持)
   level0_merge_threshold={1-2048}
   // 控制 MARS2 单表 L0 -> L1 升级的大小,当 L0 发生合并后结果 Run 超过这个大小将升级到 L1
    *(v4.5.0 开始支持)
    */
   level0_upgrade_size={1-10000}
   /* 控制 MARS2 单表 L1 -> L2 升级的大小,当 L1 发生合并后结果 Run 超过这个大小将升级到 L2
    *(v4.5.0 开始支持)
    */
   level1_upgrade_size={1-10000}
   // 控制 MARS2 表单个插入的排序内存大小,如果插入目标表是分区表,它们将共享这个大小(v4.5.0 开始支持)
   sortheap_sort_mem={128-2147483647}
   // 控制 MARS2 单个分区表至少分配多少排序内存(v4.5.0 开始支持)
   sortheap_sort_mem_core={128-2147483647}
   /* 压缩阈值。用于控制 MARS2 单表每一列的多少元组(Tuple)进行一次压缩,
    * 是同一个单元中压缩的 Tuple 数上限(v5.0.0 开始支持)
    */
   compress_threshold={1-100000}

   // 以下为 MARS3 表相关参数(均从 v5.1.0 开始支持)
   /* rowstore_size 用于控制 MARS3 表中 L0 Run 何时切换。当数据大小超过该值(单位 MB),将会切换下一个 Run;
    * compress_threshold 同 MARS2;prefer_load_mode 用于指定数据在 MARS3 中的加载模式。normal 表示正常模式,
    * 数据会按照行存落盘,再随着更多数据的写入逐渐转换为列存。bluk 表示批量加载模式,数据会直接在内存中转换成列存再落盘。
    * 当一批插入的数据量超过 rowstore_size,会分多次转换成多个列存;
    * level_size_amplifier 用于指定 Level 尺寸的放大系数
    */
   compress_threshold={1-100000},mars3options='rowstore_size={8-1024},prefer_load_mode={NORMAL|BLUK},level_size_amplifier={1-1000}'
   // 以下为 MARS3 表降级存储功能相关参数(均从 v5.2.0 开始支持)
   /* ttl_interval 用于指定数据由热至冷的阈值,需要手动指定单位,如 "2 H",意为两小时前的数据均被定义为冷数据,会进行自动降级;
    * ttl_interval 目前支持 d(天)/H(小时)单位;
    * ttl_space 指对应的表空间,不存在则无法创建;
    * ttl_interval、ttl_space 均需在建表时声明或在已有表上用 ALTER 语句设置。
    */
   ttl_interval={1-INT_MAX},ttl_space={}

key_action 是:

    ON DELETE
   | ON UPDATE
   | NO ACTION
   | RESTRICT
   | CASCADE
   | SET NULL
   | SET DEFAULT

partition_type 是:

    LIST | RANGE

partition_specification 是:

partition_element [, ...]

partition_element 是:

   DEFAULT PARTITION
                name
   | [PARTITION name] VALUES (list_value [,...] )
   | [PARTITION name]
      START ([datatype] 'start_value') [INCLUSIVE | EXCLUSIVE]
      [ END ([datatype] 'end_value') [INCLUSIVE | EXCLUSIVE] ]
      [ EVERY ([datatype] [number |INTERVAL] 'interval_value') ]
   | [PARTITION name]
      END ([datatype] 'end_value') [INCLUSIVE | EXCLUSIVE]
      [ EVERY ([datatype] [number |INTERVAL] 'interval_value') ]
[ WITH ( partition_storage_parameter=value [, ... ] ) ]
[ column_reference_storage_directive [, ...] ]
[ TABLESPACE tablespace ]

其中 subpartition_spec 或 template_spec 是:

subpartition_element [, ...]

subpartition_element 是:

   DEFAULT SUBPARTITION name
    | [SUBPARTITION name] VALUES (list_value [,...] )
    | [SUBPARTITION name]
       START ([datatype] 'start_value') [INCLUSIVE | EXCLUSIVE]
       [ END ([datatype] 'end_value') [INCLUSIVE | EXCLUSIVE] ]
       [ EVERY ([datatype] [number |INTERVAL] 'interval_value') ]
    | [SUBPARTITION name]
       END ([datatype] 'end_value') [INCLUSIVE | EXCLUSIVE]
       [ EVERY ([datatype] [number |INTERVAL] 'interval_value') ]
[ WITH ( partition_storage_parameter=value [, ... ] ) ]
[ column_reference_storage_directive [, ...] ]
[ TABLESPACE tablespace ]

其中分区的 partition_storage_parameter 是:

   appendoptimized={TRUE|FALSE}
   blocksize={8192-2097152}
   orientation={COLUMN|ROW}
   checksum={TRUE|FALSE}

   // 以下为编码链相关参数
   compresstype={ZLIB|ZSTD|QUICKLZ|RLE_TYPE|NONE|MXCUSTOM}
   // 当 compresstype=MXCUSTOM,需指定具体的 encodechain
   encodechain={LZ4|ZSTD|DELTADELTA(缩放位数)|DELTAZIGZAG|GORILLA|GORILLA2|FLOATINT|FDS|AUTO}
   /* 当 compresstype=MXCUSTOM,且 encodechain=AUTO 时,支持在表级别指定自适应编码模式:     
    * automode=1 表示压缩率优先,automode=2 表示速度优先 
    */
   automode={1|2}
   compresslevel={0-9}

   fillfactor={10-100}
   [oids=FALSE]

   // 以下为 MARS2 表相关参数
   // 用于控制所有的 MARS2 表,L0 达到多少个 Run 触发合并(v4.5.0 开始支持)
   sortheap_automerge_threshold={10-2048}
   // 用于控制 MARS2 单表 L0 达到多少个Run 触发合并(v4.5.0 开始支持)
   level0_merge_threshold={1-2048}
   // 控制 MARS2 单表 L0 -> L1 升级的大小,当 L0 发生合并后结果 Run 超过这个大小将升级到 L1
    *(v4.5.0 开始支持)
    */
   level0_upgrade_size={1-10000}
   /* 控制 MARS2 单表 L1 -> L2 升级的大小,当 L1 发生合并后结果 Run 超过这个大小将升级到 L2
    *(v4.5.0 开始支持)
    */
   level1_upgrade_size={1-10000}
   // 控制 MARS2 表单个插入的排序内存大小,如果插入目标表是分区表,它们将共享这个大小(v4.5.0 开始支持)
   sortheap_sort_mem={128-2147483647}
   // 控制 MARS2 单个分区表至少分配多少排序内存(v4.5.0 开始支持)
   sortheap_sort_mem_core={128-2147483647}
   /* 压缩阈值。用于控制 MARS2 单表每一列的多少元组(Tuple)进行一次压缩,
    * 是同一个单元中压缩的 Tuple 数上限(v5.0.0 开始支持)
    */
   compress_threshold={1-100000}

   // 以下为 MARS3 表相关参数(均从 v5.1.0 开始支持)
   /* rowstore_size 用于控制 MARS3 表中 L0 Run 何时切换。当数据大小超过该值(单位 MB),将会切换下一个 Run;
    * compress_threshold 同 MARS2;prefer_load_mode 用于指定数据在 MARS3 中的加载模式。normal 表示正常模式,
    * 数据会按照行存落盘,再随着更多数据的写入逐渐转换为列存。bluk 表示批量加载模式,数据会直接在内存中转换成列存再落盘。
    * 当一批插入的数据量超过 rowstore_size,会分多次转换成多个列存;
    * level_size_amplifier 用于指定 Level 尺寸的放大系数
    */
   compress_threshold={1-100000},mars3options='rowstore_size={8-1024},prefer_load_mode={NORMAL|BLUK},level_size_amplifier={1-1000}'
   // 以下为 MARS3 表降级存储功能相关参数(均从 v5.2.0 开始支持)
   /* ttl_interval 用于指定数据由热至冷的阈值,需要手动指定单位,如 "2 H",意为两小时前的数据均被定义为冷数据,会进行自动降级;
    * ttl_interval 目前支持 d(天)/H(小时)单位;
    * ttl_space 指对应的表空间,不存在则无法创建;
    * ttl_interval、ttl_space 均需在建表时声明或在已有表上用 ALTER 语句设置。
    */
   ttl_interval={1-INT_MAX},ttl_space={}

注意!
MARS2(v4.5.0 及之后)、MARS3 存储引擎(v5.1.0 及之后)参数详解请点击 这里

描述

CREATE TABLE 在当前数据库中创建一个最初为空的表。 执行命令的用户拥有该表。

为了能够创建表,您必须分别对所有列类型或 OF 子句中的类型具有 USAGE 特权。

如果指定模式名称,YMatrix 将在指定的模式中创建表。否则,YMatrix 将在当前模式中创建表。临时表存在于特殊的模式中,因此在创建临时表时不能指定模式名称。表名称必须与同一模式中的任何其他表,外部表,序列,索引,视图或外部表的名称不同。

CREATE TABLE 还会自动创建一个数据类型,该数据类型表示与表的一行相对应的复合类型。 因此,表不能与同一模式中的任何现有数据类型具有相同的名称。

可选的约束子句指定新行或更新行必须满足的条件才能成功执行插入或更新操作。约束是一个 SQL 对象,可以通过多种方式帮助定义表中的有效值集。约束适用于表,而不适用于分区。您不能将约束添加到分区或子分区。

引用完整性约束(外键)被接受但不强制执行。 该信息保留在系统 catalog 中,否则将被忽略。

有两种定义约束的方法:表约束和列约束。列约束被定义为列定义的一部分。表约束定义不与特定列绑定,并且可以包含多个列。每个列约束也可以写为表约束。当约束仅影响一列时,使用列约束只是一种符号上的方便。

创建表时,还有一个附加子句来声明 YMatrix 数据库分发策略。 如果未提供 DISTRIBUTED BY,DISTRIBUTED RANDOMLY 或 DISTRIBUTED REPLICATED 子句, 则 YMatrix 数据库将通过使用 PRIMARY KEY(如果表具有一个)或表的第一列作为分发键,向该表分配哈希分发策略。几何或用户定义数据类型的列不符合 YMatrix 分布键列的要求。 如果表中没有符合条件的数据类型的列,则将根据轮询或随机分布来分配行。为了确保数据在 YMatrix 数据库系统中的均匀分配,您希望选择一个对于每个记录都是唯一的分配键,或者如果不可能,则选择 DISTRIBUTED RANDOMLY。

如果提供了 DISTRIBUTED REPLICATED 子句,则 YMatrix 数据库会将表的所有行分配给 YMatrix 数据库系统中的所有 Segment。 如果用户定义的函数必须在 Segment 上执行,并且这些函数需要访问表的所有行,则可以使用此选项。 复制函数还可以用于防止表的 Broadcast Motions,从而提高查询性能。 DISTRIBUTED REPLICATED 子句不能与 PARTITION BY 子句或 INHERITS 子句一起使用。 复制的表也不能被另一个表继承。 隐藏的系统列(ctid,cmin,cmax,xmin, xmax 和 gp_segment_id)无法在复制表的用户查询中引用,因为它们没有单一的,无歧义的值。

通过 PARTITION BY 子句,您可以将表分为多个子表(或部分),这些子表一起构成父表并共享其模式。 尽管子表作为独立表存在,但是 YMatrix 数据库以重要方式限制了它们的使用。在内部,分区被实现为继承的一种特殊形式。每个子表分区都是根据不同的 CHECK 约束创建的,该约束根据一些定义条件限制表可以包含的数据。查询优化器还使用 CHECK 约束来确定要扫描哪些表分区以满足给定的查询谓词。 这些分区约束由 YMatrix 数据库自动管理。

YMatrix v5.0.0 开始支持建表时指定自定义编码链算法进行压缩。详见使用压缩

参数

GLOBAL | LOCAL

  • 提供这些关键字是为了实现 SQL 标准兼容性,但在 YMatrix 数据库中无效,并且已弃用。

TEMPORARY | TEMP

  • 如果指定,该表将被创建为临时表。临时表在会话结束时或在当前事务结束时自动删除(请参见 ON COMMIT)。 临时表存在时,具有相同名称的现有永久表在当前会话中不可见,除非使用模式限定名称引用它们。 在临时表上创建的所有索引也会自动成为临时索引。

UNLOGGED

  • 如果指定,该表将创建为未记录表。写入未记录表的数据不会写入预写(WAL)日志,这使它们比普通表快得多。 但是,未记录表的内容不会复制到 Mirror 实例。 同样,未记录的表也不是崩溃安全的。 Segment 实例崩溃或异常关闭后,该 Segment 上未记录表的数据将被截断。 在未记录表上创建的所有索引也会自动成为未记录索引。

table_name

  • 要创建的新表的名称(可以由模式指定)。

OF type_name

  • 创建一个类型化的表,该表从指定的组合类型(名称可以由模式指定)获取其结构。 类型化的表与其类型相关联。 例如,如果删除了类型(使用 DROP TYPE ... CASCADE),则将删除该表。 当一个类型化的表被创建时,列的数据类型由底层的组合类型决定而没有在 CREATE TABLE 命令中直接指定。 但是 CREATE TABLE 命令可以对表增加默认值和约束,并且可以指定存储参数。

column_name

  • 要在新表中创建的列的名称。

data_type

  • 列的数据类型。这可能包括数组说明符。
    对于包含文本数据的表列,请指定数据类型 VARCHAR 或 TEXT。 不建议指定数据类型 CHAR。 在 YMatrix 数据库中,数据类型 VARCHAR 或 TEXT 处理作为有效字符添加到数据 (在最后一个非空格字符之后添加的空格字符)的填充,而数据类型 CHAR 不处理。

COLLATE collation

  • COLLATE 子句为该列分配排序规则(该排序规则必须是可排序的数据类型)。 如果未指定,则使用列数据类型的默认排序规则。

DEFAULT default_expr

  • DEFAULT 子句为出现在其列定义中的列分配默认数据值。 该值是任何不带变量的表达式(不允许对当前表中的其他列进行子查询和交叉引用)。 默认表达式的数据类型必须与列的数据类型匹配。 默认表达式将在未为列指定值的任何插入操作中使用。 如果列没有默认值,则默认值为 NULL。

ENCODING ( storage_directive [, ...] )

  • 对于列,可选的 ENCODING 子句指定列数据的压缩类型和块大小。
    该子句仅对追加优化的,面向列的表有效。
    列压缩设置从表级别继承到分区级别再到子分区级别。 最低级别的设置具有优先权。

INHERITS ( parent_table [, …])

  • 可选的 INHERITS 子句指定一个表列表,新表将从中自动继承所有列。 使用 INHERITS 将在新的子表及其父表之间创建持久关系。 对父级的模式修改通常也会传播到子级,默认情况下,子级表的数据包含在父级扫描中。
    在 YMatrix 数据库中,创建分区表时不使用 INHERITS 子句。 尽管在分区层次结构中使用了继承的概念,但是使用 PARTITION BY 子句创建了分区表的继承结构。
    如果一个以上的父表中存在相同的列名,则将报告错误,除非每个父表中的列的数据类型都匹配。 如果没有冲突,则将重复的列合并以在新表中形成一个列。 如果新表的列名列表包含一个也被继承的列名,则数据类型必须同样与继承的列匹配,并且列定义将合并为一个。 如果新表显式指定了该列的默认值,则该默认值将覆盖该列的继承声明中的所有默认值。 否则,为该列指定默认值的所有父项都必须指定相同的默认值,否则将报告错误。
    CHECK 约束基本上以与列相同的方式合并: 如果多个父表或新表定义包含名称相同的约束,则这些约束必须全部具有相同的校验表达式,否则将报告错误。 具有相同名称和表达式的约束将合并为一个副本。 不会考虑在父级中标记为 NO INHERIT 的约束。 请注意,新表中未命名的 CHECK 约束将永远不会被合并,因为将始终为其选择唯一的名称。 列 STORAGE 设置也会从父表中复制。

LIKE source_table like_option ...]

  • LIKE 子句指定一个表,新表将从该表中自动复制所有列名,其数据类型,非空约束和分发策略。 不会复制诸如追加优化或分区结构之类的存储属性。 与 INHERITS 不同,新表和原始表在创建完成后完全解耦。
    仅当指定 INCLUDING DEFAULTS 时,才会复制复制的列定义的默认表达式。 默认行为是排除默认表达式,导致新表中复制的列具有空默认值。
    非空约束始终会复制到新表中。 仅当指定 INCLUDING CONSTRAINTS 时,才会复制 CHECK 约束。 列约束和表约束之间没有区别。
    仅在指定 INCLUDING INDEXES 子句的情况下,才会在新表上创建原始表的索引, PRIMARY KEY 和 UNIQUE 约束。 不论原始名称如何命名,都会根据默认规则选择新索引和约束的名称。 (此行为避免了新索引可能出现的重复名称错误。)
    除非指定了 INCLUDING INDEXES 子句,否则不会在新表上创建原始表上的任何索引。
    仅当指定了 INCLUDING STORAGE 时,才会复制复制的列定义的 STORAGE 设置。 默认行为是排除 STORAGE 设置,导致新表中复制的列具有特定于类型的默认设置。
    仅当指定 INCLUDING COMMENTS 时,才会复制复制的列,约束和索引的注释。 默认行为是排除注释,导致新表中复制的列和约束没有注释。
    INCLUDING ALL 是 INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS 的缩写形式。
    请注意,与 INHERITS 不同,LIKE 复制的列和约束不会与名称相似的列和约束合并。 如果显式指定了相同的名称,或者在另一个 LIKE 子句中指定了相同的名称,则将指示错误。
    LIKE 子句还可用于从视图,外部表或复合类型中复制列。 不适用的选项(例如,从视图 INCLUDING INDEXES)将被忽略。

CONSTRAINT constraint_name

  • 列或表约束的可选名称。 如果违反了约束,那么约束名称将出现在错误消息中,因此可以使用约束名称(例如列必须为正)来将有用的约束信息传达给客户端应用程序。 (需要双引号指定包含空格的约束名称。)如果未指定约束名称,则系统将生成一个名称。
    注意:指定的 constraint_name 用于约束,但系统生成的唯一名称用于索引名。 在某些以前的版本中,提供的名称同时用于约束名称和索引名称。

NULL | NOT NULL

  • 指定是否允许该列包含空值。默认值为 NULL。

CHECK (expression) [ NO INHERIT ]

  • CHECK 子句指定一个生成布尔结果的表达式,新的或更新的行必须满足才能使插入或更新操作成功。 计算为 TRUE 或 UNKNOWN 的表达式会成功。 如果插入或更新操作的任何行都产生 FALSE 结果,则会引发错误异常,并且插入或更新不会更改数据库。 指定为列约束的检查约束应仅引用该列的值,而出现在表约束中的表达式可以引用多个列。
    标有 NO INHERIT 的约束不会传播到子表。
    当前,CHECK 表达式不能包含子查询,也不能引用当前行的列以外的变量。

UNIQUE ( column_constraint )

UNIQUE ( column_name [, ... ] ) ( table_constraint )

  • UNIQUE 约束指定表的一组一个或多个列只能包含唯一值。 唯一表约束的行为与列约束的行为相同,但具有跨多个列的附加功能。 出于唯一约束的目的,空值不视为相等。 唯一的列必须包含 YMatrix 分布键的所有列。 此外,如果表已分区,则键必须包含分区键中的所有列。 请注意,分区表中的键约束与简单的 UNIQUE INDEX 不同。

PRIMARY KEY ( column constraint )

PRIMARY KEY ( column_name [, ... ] ) ( table constraint )

  • PRIMARY KEY 约束指定表的一列或多列只能包含唯一(非重复),非 NULL 值。 只能为一个表指定一个主键,无论是作为列约束还是表约束。
    要使一个表具有主键,它必须是哈希分布的(不是随机分布的),并且主键(唯一的列)必须包含 YMatrix 分布键的所有列。 此外,如果表已分区,则键必须包含分区键中的所有列。 请注意,分区表中的键约束与简单的 UNIQUE INDEX 不同。
    PRIMARY KEY 强制执行与 UNIQUE和NOT NULL 相同的组合数据约束, 但是将一组列标识为主键也可以提供有关模式设计的元数据,因为主键标识其他表可以依赖这一个列集合作为行的唯一标识符。

REFERENCES reftable [ ( refcolumn ) ]

[ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]

[ON DELETE | ON UPDATE] [key_action]

FOREIGN KEY (column_name [, ...])

  • REFERENCES 和 FOREIGN KEY 子句指定引用完整性约束(外键约束)。 YMatrix 接受 PostgreSQL 语法中指定的参照完整性约束,但不强制执行。 有关引用完整性约束的信息,请参见 PostgreSQL 文档。

DEFERRABLE

NOT DEFERRABLE

  • [NOT] DEFERRABLE 子句控制约束是否可以被推迟。 一个不可推迟的约束将在每个命令后立即进行检查。 可以推迟检查约束,直到事务结束(使用 SET CONSTRAINTS 命令)。 默认值是 NOT DEFERRABLE。 当前,只有 UNIQUE 和 PRIMARY KEY 约束是可推迟的。 NOT NULL 和 CHECK 约束不可延迟。 REFERENCES(外键)约束接受此子句,但不强制执行。

INITIALLY IMMEDIATE

INITIALLY DEFERRED

  • 如果约束是可延迟的,则此子句指定检查约束的默认时间。 如果该约束是 INITIALLY IMMEDIATE,则在每个语句之后对其进行检查。 这是默认值。 如果约束是 INITIALLY DEFERRED,则仅在事务结束时进行检查。 可以使用 SET CONSTRAINTS 命令更改约束检查时间。

WITH ( storage_parameter=value )

  • WITH 子句可以为表以及与 UNIQUE 或 PRIMARY 约束关联的索引指定存储参数。 请注意,您还可以通过在分区规范中声明 WITH 子句来在特定分区或子分区上设置存储参数。 最低级别的设置具有优先权。
    某些表存储选项的默认值可以使用服务器配置参数 gp_default_storage_options 指定。
    可以使用以下存储选项:
    • appendoptimized — 设置为 TRUE 可将表创建为追加优化的表。 如果为 FALSE 或未声明,则将表创建为常规堆存储表。
    • blocksize — 设置为表中每个块的大小(以字节为单位)。 blocksize 必须介于 8192 和 2097152 字节之间,并且是 8192 的倍数。默认值为 32768。
    • orientation — 设置为 column 以用于列式存储,或设置为 row(默认)以用于行式存储。 仅当 appendoptimized = TRUE 时,此选项才有效。堆存储表只能是面向行的。
    • checksum — 此选项仅对追加优化的表(appendoptimized = TRUE)有效。 值 TRUE 是默认值,并为追加优化表启用 CRC 校验和验证。 校验和是在块创建期间计算的,并存储在磁盘上。 在块读取期间执行校验和验证。 如果在读取期间计算出的校验和与存储的校验和不匹配,则事务中止。 如果将值设置为 FALSE 以禁用校验和验证,将不会执行检查表数据是否存在磁盘损坏的操作。
    • compresstype — 设置为 ZLIB(默认值),ZSTD,RLE_TYPE,QUICKLZ1 或使用编码链 MXCUSTOM 以指定使用的压缩类型。值 NONE 禁用压缩。ZSTD 提供速度或良好的压缩率,可通过 compresslevel 选项进行调整。 提供 QuickLZ 和 ZLIB 是为了向后兼容。 在通常的工作负载上,ZSTD 的性能优于这些压缩类型。 仅当 appendoptimized = TRUE 时,compresstype 选项才有效。
      仅当指定了 orientation = column 时才支持值 RLE_TYPE,它启用游程编码(RLE)压缩算法。 当相同的数据值出现在许多连续的行中时,RLE 的压缩数据比 ZSTD,ZLIB 或 QuickLZ 压缩算法更好。
      对于 BIGINT,INTEGER,DATE, TIME 或 TIMESTAMP 类型的列,如果将 compresstype 选项设置为 RLE_TYPE 压缩,则还将应用增量压缩。 增量压缩算法基于连续行中列值之间的增量,旨在改善按排序顺序加载数据或将压缩应用于按排序顺序的列数据时的压缩。如果使用编码链,则需在 compresstype 后利用 encodechain 参数指定具体的编码链算法,详见 使用压缩在 WITH 语句中指定的编码链压缩是表级别的。
    • compresslevel — 对于追加优化表的 ZSTD 压缩,请将其设置为 1(最快压缩)到 19(最高压缩率)之间的整数值。 对于 ZLIB 压缩,有效范围是 1 到 9。QuickLZ 压缩级别只能设置为 1。 如果未声明,则默认值为 1。 对于 RLE_TYPE,压缩级别可以是 1(最快压缩)到 4(最高压缩率)之间的整数值。仅当 appendoptimized = TRUE 时,compresslevel 选项才有效。
    • fillfactor — fillfactor 是一个 10 到 100 的百分比数值,默认 100。当指定更小的值时,页内剩余空间会预留给更新行时使用。这使得做更新时,更新后的行会放到相同的页里,与放到不同页里相比会更高效。对于从不更新的表使用默认值即可,对于大量更新的表则适当调小。这个参数对于 TOAST 表无法设置。
    • oids=FALSE — 这是默认值,每个数据行内没有分配 oid。 在大型表上(例如典型的 YMatrix 数据库系统中的表),对表行使用 OID 可能会导致 32 位 OID 计数器的折回。 一旦计数器回绕,就不能再认为 OID 是唯一的,这不仅使它们对用户应用程序无用, 而且还会在 YMatrix 数据库系统 catalog 表中引起问题。 此外,从表中排除 OID 会使表每行存储在磁盘上所需的空间减少了每行 4 个字节,从而略微提高了性能。 分区表或追加优化的面向列的表上不允许使用 OIDS。
    • MARS2、MARS3 相关参数详见存储引擎原理

ON COMMIT

  • 可以使用 ON COMMIT 控制事务块末尾的临时表的行为。 这三个选项是:
    • PRESERVE ROWS - 临时表的事务结束时不会采取任何特殊操作。这是默认行为。
    • DELETE ROWS - 临时表中的所有行将在每个事务块的末尾删除。 本质上,每次提交都会自动执行一次TRUNCATE。
    • DROP - 临时表将在当前事务块的末尾删除。

TABLESPACE tablespace

  • 要在其中创建新表的表空间的名称。如果未指定,则使用数据库的默认表空间。

USING INDEX TABLESPACE tablespace

  • 该子句允许选择将在其中创建与 UNIQUE 或 PRIMARY KEY 约束关联的索引的表空间。 如果未指定,则使用数据库的默认表空间。

DISTRIBUTED BY (column [opclass], [ ... ] )

DISTRIBUTED RANDOMLY

DISTRIBUTED REPLICATED

  • 用于声明表的 YMatrix 数据库分布策略。 DISTRIBUTED BY 使用具有一个或多个声明为分布键的列的哈希分布。 为了获得最均匀的数据分配,分布键应为表的主键或唯一列(或一组列)。 如果无法做到这一点,则可以选择 DISTRIBUTED RANDOMLY,它将数据轮询发送到 Segment 实例。 此外,可以指定运算符类 opclass,以使用非默认哈希函数。
    如果在创建表时未指定 DISTRIBUTED BY 子句, 则 YMatrix 数据库服务器配置参数 gp_create_table_random_default_distribution 将控制表默认分布策略。 如果未指定分布策略,YMatrix 数据库将遵循以下规则来创建表:
    • 如果指定了 LIKE 或 INHERITS 子句,则 YMatrix 从源表或父表复制分布键。
    • 如果指定了 PRIMARY KEY 或 UNIQUE 约束,则 YMatrix 选择所有键列中最大的子集作为分布键。
    • 如果既未指定约束,也未指定 LIKE 或 INHERITS 子句,则 YMatrix 选择第一个合适的列作为分布键。 (具有几何或用户定义数据类型的列不符合作为 YMatrix 分布键列的条件。)

如果参数的值设置为 on,则 YMatrix 数据库遵循以下规则:

  • 如果未指定 PRIMARY KEY 或 UNIQUE 列, 则表的分布是随机的(DISTRIBUTED RANDOMLY)。 即使表创建命令包含 LIKE 或 INHERITS 子句,表分布也是随机的。
  • 如果指定了 PRIMARY KEY 或 UNIQUE 列,则还必须指定 DISTRIBUTED BY 子句。 如果在表创建命令中未指定 DISTRIBUTED BY 子句,则该命令将失败。

DISTRIBUTED REPLICATED 子句将整个表复制到所有 YMatrix 数据库 Segment 实例。 当函数需要访问表中的所有行或需要通过阻止 Broadcast Motion 来提高查询性能时,必须在 Segment 上执行用户定义的函数时可以使用它。

PARTITION BY

  • 声明用于对表进行分区的一列或多列。
    创建分区表时,YMatrix 数据库使用指定的表名创建根分区表(根分区)。 YMatrix 数据库还会根据您指定的分区选项创建表,子表的层次结构,这些表是子分区。 YMatrix 数据库 pg_partition* 系统视图包含有关子分区表的信息。
    对于每个分区级别(表的每个层次结构级别),一个分区表最多可以有 32,767 个分区。
    注意:YMatrix 数据库将分区表数据存储在叶子表中,叶子表是子表层次结构中的最低层表,供分区表使用。

    • partition_type
      • 声明分区类型:LIST(值列表)或 RANGE(数字或日期范围)。
    • partition_specification
      • 声明要创建的各个分区。 可以单独定义每个分区,或者对于范围分区,可以使用 EVERY 子句(带有 START 和可选 END 子句)来定义用于创建单个分区的增量模式。
        DEFAULT PARTITION name — 声明默认分区。 当数据与现有分区不匹配时,会将其插入默认分区。 没有默认分区的分区设计将拒绝与现有分区不匹配的传入行。
        PARTITION name — 声明要用于分区的名称。 使用以下命名约定创建分区:parentname_level#_prt_givenname。
        VALUES — 对于列表分区,定义分区将包含的值。
        START — 对于范围分区,定义分区的起始范围值。 默认情况下,起始值为 INCLUSIVE。 例如,如果您声明开始日期为 '2016-01-01', 则分区将包含所有大于或等于 '2016-01-01' 的日期。 通常,START 表达式的数据类型与分区键列的类型相同。 如果不是这种情况,则必须显式转换为预期的数据类型。
        END — 对于范围分区,定义分区的结束范围值。 默认情况下,结束值为 EXCLUSIVE。 例如,如果您声明结束日期为 '2016-02-01', 则分区将包含所有小于但不等于 '2016-02-01' 的日期。 通常,END 表达式的数据类型与分区键列的类型相同。 如果不是这种情况,则必须显式转换为预期的数据类型。
        EVERY — 对于范围分区,定义如何将值从 START 递增到 END 以创建单个分区。 通常,EVERY 表达式的数据类型与分区键列的类型相同。 如果不是这种情况,则必须显式转换为预期的数据类型。
        WITH — 设置分区的表存储选项。 例如,您可能希望将较旧的分区作为追加优化表,而将较新的分区作为常规堆表。
        TABLESPACE — 要在其中创建分区的表空间的名称。

SUBPARTITION BY

  • 声明用于对表的第一级分区进行子分区的一个或多个列。 子分区的规范格式类似于上述分区的规范格式。

SUBPARTITION TEMPLATE

  • 您可以选择声明一个用于创建子分区的子分区模板(低级别子表),而不是为每个分区分别声明每个子分区定义。 然后,此子分区规范将应用于所有父分区。

注解

  • 在 YMatrix 数据库(基于 Postgres 的系统)中, 数据类型 VARCHAR 或 TEXT 处理填充作为有效字符添加到文本的数据(最后一个非空格字符之后添加空格字符); 数据类型 CHAR 则没有。
  • 在 YMatrix 数据库中,CHAR(n) 类型的值用尾随空格填充到指定的宽度 n。 值将存储并显示为空格。 但是,填充空格在语义上无关紧要。 分配值时,将忽略尾随空格。 比较数据类型 CHAR 的两个值时,尾随空格在语义上也无关紧要, 而将字符值转换为其他字符串类型之一时,尾随空格也将被删除。
  • 不建议在新应用程序中使用 OID:在可能的情况下,最好使用 SERIAL 或其他序列生成器作为表的主键。 但是,如果您的应用程序确实使用 OID 来标识表的特定行, 则建议在该表的 OID 列上创建唯一约束,以确保即使在计数器回绕后,表中的 OID 的确可以唯一地标识行。 避免假设 OID 在表之间是唯一的;如果需要数据库范围的唯一标识符,则可以使用表 OID 和行 OID 的组合。
  • YMatrix 数据库对于主键和作为 YMatrix 表中的分布键的列的唯一约束具有一些特殊条件。为了在 YMatrix 数据库中实施唯一约束,表必须是哈希分布的(不是 DISTRIBUTED RANDOMLY), 并且约束列必须与表的分布键列相同(或作为其的超集)。 另外,分布键必须是约束列的左子集,并且列的顺序正确。 例如,如果主键是(a,b,c),则分布键只能是以下之一:(a),(a,b)或(a,b,c)。
    复制表(DISTRIBUTED REPLICATED)可以同时具有 PRIMARY KEY 和 UNIQUE 列约束。
    主键约束只是唯一约束和非空约束的组合。
    YMatrix 数据库自动为每个 UNIQUE 或 PRIMARY KEY 约束创建一个 UNIQUE 索引,以强制执行唯一性。 因此,没有必要为主键列显式创建索引。 在追加优化表上不允许使用 UNIQUE 和 PRIMARY KEY 约束,因为在追加优化表上不允许通过约束创建的 UNIQUE 索引。
    YMatrix 数据库中不支持外键约束。
    对于继承的表,当前实现中不会继承唯一约束,主键约束,索引和表特权。
  • 对于追加优化的表,可重复读或可序列化事务中不允许 UPDATE 和 DELETE,这将导致事务中止。 CLUSTER,DECLARE...FOR UPDATE 和触发器不支持追加优化的表。
  • 要将数据插入分区表中,请指定根分区表,即使用 CREATE TABLE 命令创建的表。 您还可以在 INSERT 命令中指定分区表的叶子表。 如果数据对于指定的叶子表无效,则返回错误。 不支持在 INSERT 命令中指定不是叶子表的子表。 不支持在分区表的任何子表上执行其他 DML 命令,例如 UPDATE 和 DELETE。 这些命令必须在根分区表(使用 CREATE TABLE 命令创建的表)上执行。

示例

在名为 baby 的模式中创建一个名为 rank 的表, 并使用 rank,gender 和 year 列分发数据:

CREATE TABLE baby.rank (id int, rank int, year smallint,
gender char(1), count int ) DISTRIBUTED BY (rank, gender,
year);

创建表 files 和表分配器(默认情况下,主键将用作 YMatrix 分布键):

CREATE TABLE films (
code        char(5) CONSTRAINT firstkey PRIMARY KEY,
title       varchar(40) NOT NULL,
did         integer NOT NULL,
date_prod   date,
kind        varchar(10),
len         interval hour to minute
);

CREATE TABLE distributors (
did    integer PRIMARY KEY DEFAULT nextval('serial'),
name   varchar(40) NOT NULL CHECK (name <> '')
);

创建一个 gzip 压缩的,追加优化的表:

CREATE TABLE sales (txn_id int, qty int, date date) 
WITH (appendoptimized=true, compresslevel=5) 
DISTRIBUTED BY (txn_id);

创建一个简单的,单级别的分区表:

CREATE TABLE sales (id int, year int, qtr int, c_rank int, code char(1), region text)
DISTRIBUTED BY (id)
PARTITION BY LIST (code)
( PARTITION sales VALUES ('S'),
  PARTITION returns VALUES ('R')
);

不使用 SUBPARTITION TEMPLATE 子句创建三级分区表:

CREATE TABLE sales (id int, year int, qtr int, c_rank int, code char(1), region text)
DISTRIBUTED BY (id)
PARTITION BY LIST (code)
  SUBPARTITION BY RANGE (c_rank)
    SUBPARTITION by LIST (region)

( PARTITION sales VALUES ('S')
   ( SUBPARTITION cr1 START (1) END (2)
      ( SUBPARTITION ca VALUES ('CA') ), 
      SUBPARTITION cr2 START (3) END (4)
        ( SUBPARTITION ca VALUES ('CA') ) ),

 PARTITION returns VALUES ('R')
   ( SUBPARTITION cr1 START (1) END (2)
      ( SUBPARTITION ca VALUES ('CA') ), 
     SUBPARTITION cr2 START (3) END (4)
        ( SUBPARTITION ca VALUES ('CA') ) )
);

使用 SUBPARTITION TEMPLATE 子句创建与前例相同的分区表:

CREATE TABLE sales1 (id int, year int, qtr int, c_rank int, code char(1), region text)
DISTRIBUTED BY (id)
PARTITION BY LIST (code)

   SUBPARTITION BY RANGE (c_rank)
     SUBPARTITION TEMPLATE (
     SUBPARTITION cr1 START (1) END (2),
     SUBPARTITION cr2 START (3) END (4) )

     SUBPARTITION BY LIST (region)
       SUBPARTITION TEMPLATE (
       SUBPARTITION ca VALUES ('CA') )

( PARTITION sales VALUES ('S'),
  PARTITION  returns VALUES ('R')
) ;

创建一张三级分区表,并在每级使用子分区模板和默认分区:

CREATE TABLE sales (id int, year int, qtr int, c_rank int, code char(1), region text)
DISTRIBUTED BY (id)
PARTITION BY RANGE (year)

  SUBPARTITION BY RANGE (qtr)
    SUBPARTITION TEMPLATE (
    START (1) END (5) EVERY (1), 
    DEFAULT SUBPARTITION bad_qtr )

    SUBPARTITION BY LIST (region)
      SUBPARTITION TEMPLATE (
      SUBPARTITION usa VALUES ('usa'),
      SUBPARTITION europe VALUES ('europe'),
      SUBPARTITION asia VALUES ('asia'),
      DEFAULT SUBPARTITION other_regions)

( START (2009) END (2011) EVERY (1),
  DEFAULT PARTITION outlying_years);

指定新分区的 SEGMENT_SET 对象:

## 创建 SEGMENT_SET 对象 ss1
CREATE SEGMENT_SET ss1 SEGMENTS('0,2');

## 创建 t 表
CREATE TABLE t(a int, b int) DISTRIBUTED BY(a) PARTITION BY RANGE(b) (DEFAULT PARTITION others SEGMENT_SET ss1);

## 指定新分区的 SEGMENT_SET 对象
CREATE TABLE t_part_manual PARTITION OF t FOR VALUES FROM (3) TO (6) SEGMENT_SET ss1;

创建 MARS2 表。MARS2 表依赖 matrixts 扩展,在建表前,首先需要你在使用该存储引擎的数据库中创建扩展。

CREATE EXTENSION matrixts;

创建一张可进行自适应编码压缩的表。详见使用压缩

CREATE TABLE t (
      f1 int8
    , f2 int8
) 
USING MARS2
WITH(
      compresstype=mxcustom
);

创建一张既指定表级别,又指定列级别压缩的表。列级压缩的指定要优先于表级(列指定 ENCODING(compresstype=none)/ENCODING(minmax) 例外)。详见使用压缩

CREATE TABLE t (
      f1 int8 ENCODING(compresstype=lz4)
    , f2 int8
) 
USING MARS2
WITH(
      compresstype=mxcustom
    , encodechain=auto
);
CREATE INDEX idx_mars2 ON t USING mars2_btree(f1);

注意!
matrixts 扩展为数据库级别,一个数据库里面创建一次即可,无需重复创建。

CREATE TABLE disk_mars2(
    time timestamp with time zone,
    tag_id int,
    read float,
    write float
)
USING MARS2
WITH (compresstype=zstd, compresslevel=3)
DISTRIBUTED BY (tag_id);
CREATE INDEX ON disk_mars2 USING mars2_btree(time,tag_id);

创建一个 MARS3 表。MARS3 表同样依赖 matrixts 扩展,在建表前,首先需要你在使用该存储引擎的数据库中创建扩展。

CREATE EXTENSION matrixts;
CREATE TABLE t(
    time timestamp with time zone,
    tag_id int,
    i4 int4,
    i8 int8
)
USING MARS3
WITH (compresstype=zstd, compresslevel=3,compress_threshold=1200,
        mars3options='rowstore_size=64,prefer_load_mode=normal,level_size_amplifier=8')
DISTRIBUTED BY (tag_id)
ORDER BY (time, tag_id);

兼容性

CREATE TABLE 命令符合 SQL 标准,但以下情况除外:

  • Temporary Tables — 在 SQL 标准中,临时表仅定义一次,并在每个需要它们的会话中自动存在(从空内容开始)。 相反,YMatrix 数据库要求每个会话为要使用的每个临时表发出自己的 CREATE TEMPORARY TABLE 命令。 这允许不同的会话出于不同的目的而使用相同的临时表名称,而标准的方法将给定临时表名称的所有实例约束为具有相同的表结构。
    全局和本地临时表之间的标准区别不在 YMatrix 数据库中。 YMatrix 数据库将在临时表声明中接受 GLOBAL 和 LOCAL 关键字,但它们无效且已弃用。
    如果省略 ON COMMIT 子句,则 SQL 标准将默认行为指定为 ON COMMIT DELETE ROWS。 但是,YMatrix 数据库中的默认行为是 ON COMMIT PRESERVE ROWS。 SQL 标准中不存在 ON COMMIT DROP 选项。

  • Column Check Constraints — SQL 标准说,CHECK 列约束只能引用它们所适用的列。 只有 CHECK 表约束可以引用多个列。 YMatrix 数据库不强制执行此限制;它对待列和表检查约束都一样。

  • NULL Constraint — NULL 约束是对 SQL 标准的 YMatrix 数据库扩展, 为了与某些其他数据库系统兼容(以及对称的 NOT NULL 约束)。 由于它是任何列的默认值,因此不需要它的存在。

  • Inheritance — 通过 INHERITS 子句的多重继承是 YMatrix 数据库语言的扩展。 SQL:1999 及更高版本使用不同的语法和语义定义了单个继承。 YMatrix 数据库尚不支持 SQL:1999 样式的继承。

  • Partitioning — 通过 PARTITION BY 子句进行的表分区是 YMatrix 数据库语言的扩展。

  • Zero-column tables — YMatrix 数据库允许创建不包含任何列的表(例如 CREATE TABLE foo();)。 这是 SQL 标准的扩展,不允许使用零列表。 零列表本身并没有什么用,但是不允许使用零列表在 ALTER TABLE DROP COLUMN 时会产生奇怪的特殊情况, 因此 YMatrix 决定忽略此规范限制。

  • LIKE — 尽管 SQL 标准中存在 LIKE 子句, 但 YMatrix 数据库接受的许多选项都不在该标准中,并且 YMatrix 数据库并未实现该标准的某些选项。

  • WITH clause — WITH 子句是 YMatrix 数据库扩展。 存储参数和 OID 都不在标准中。

  • Tablespaces — 表空间的 YMatrix 数据库概念不是 SQL 标准的一部分。 子句 TABLESPACE 和 USING INDEX TABLESPACE 是扩展。

  • Data Distribution — 并行或分布式数据库的 YMatrix 数据库概念不是 SQL 标准的一部分。 DISTRIBUTED 子句是扩展。

另见

ALTER TABLEDROP TABLECREATE SEGMENT SET