CREATE TABLE

创建非分区表、分区表、外部表或聚簇表。

限制条件

  • 分区表的分区层级不能超过6级。例如某张表以日期为分区列,分区层级为年/月/周/日/时/分

  • 一张表允许的分区个数支持按照具体的项目配置,默认为6万个。

更多表的限制条件,请参见SQL使用限制项

命令格式

--创建新表。
 create [external] table [if not exists] <table_name>
 [(<col_name> <data_type> [not null] [default <default_value>] [comment <col_comment>], ...)]
 [comment <table_comment>]
 [partitioned by (<col_name> <data_type> [comment <col_comment>], ...)]
 --用于创建聚簇表时设置表的Shuffle和Sort属性。
 [clustered by | range clustered by (<col_name> [, <col_name>, ...]) [sorted by (<col_name> [asc | desc] [, <col_name> [asc | desc] ...])] into <number_of_buckets> buckets] 
 --仅限外部表。
 [stored by StorageHandler] 
 --仅限外部表。
 [with serdeproperties (options)] 
 --仅限外部表。
 [location <osslocation>] 
 --指定表为Transactional表,后续可以对该表执行更新或删除表数据操作,但是Transactional表有部分使用限制,请根据需求创建。
 [tblproperties("transactional"="true")]   
 [lifecycle <days>];

--基于已存在的表创建新表并复制数据,但不复制分区属性。
create table [if not exists] <table_name> [lifecycle <days>] as <select_statement>;

--基于已存在的表创建具备相同结构的新表但不复制数据。
create table [if not exists] <table_name> like <existing_table_name> [lifecycle <days>];

参数说明

参数

是否必选

说明

external

可选。

表示创建的表为外部表。

if not exists

可选。

如果不指定if not exists选项而存在同名表,会报错。如果指定if not exists,只要存在同名表,即使原表结构与要创建的目标表结构不一致,均返回成功。已存在的同名表的元数据信息不会被改动。

table_name

必填。

表名。表名大小写不敏感,不能有特殊字符,只能包含a~z、A~Z、数字和下划线(_)。建议以字母开头,名称的长度不超过128字节,否则报错。

col_name

可选。

表的列名。列名大小写不敏感,不能有特殊字符,只能包含a~z、A~Z、数字和下划线(_)。建议以字母开头,名称的长度不超过128字节,否则报错。

col_comment

可选。

列的注释内容。注释内容为长度不超过1024字节的有效字符串,否则报错。

data_type

可选。

列的数据类型,包含BIGINT、DOUBLE、BOOLEAN、DATETIME、DECIMAL和STRING等多种数据类型,详情请参见数据类型版本说明

not null

可选。

禁止该列的值为NULL。更多修改非空属性信息,请参见修改表的列非空属性

default_value

可选。

指定列的默认值,当insert操作不指定该列时,该列写入默认值。

table_comment

可选。

表注释内容。注释内容为长度不超过1024字节的有效字符串,否则报错。

partitioned by (<col_name> <data_type> [comment <col_comment>], ...

可选。

指定分区表的分区字段。

  • col_name:表的分区列名。列名大小写不敏感,不能有特殊字符,只能包含a~z、A~Z、数字和下划线(_)。建议以字母开头,名称的长度不超过128字节,否则报错。

  • data_type:分区列的数据类型。MaxCompute 1.0版本仅支持STRING类型。MaxCompute 2.0版本扩充了分区类型,包含TINYINT、SMALLINT、INT、BIGINT、VARCHAR和STRING类型。详情请参见数据类型版本说明。当使用分区字段对表进行分区时,新增分区、更新分区内数据和读取分区数据均不需要做全表扫描,提高处理效率。

  • col_comment:分区列的注释内容。注释内容为长度不超过1024字节的有效字符串,否则报错。

说明

分区值不能包含双字节字符(如中文),必须以字母开头,包含字母、数字和允许的字符,长度不超过128字节。允许的字符包括空格、冒号(:)、下划线(_)、美元符号($)、井号(#)、英文句点(.)、感叹号(!)和at(@),其他字符的行为未定义,例如转义字符\t\n/

clustered by | range clustered by (<col_name> [, <col_name>, ...]) [sorted by (<col_name> [asc | desc] [, <col_name> [asc | desc] ...])] into <number_of_buckets> buckets

可选。

用于创建聚簇表时设置表的Shuffle和Sort属性。

聚簇表分为Hash聚簇表和Range聚簇表两种:

  • Hash聚簇表

    • clustered by:指定Hash Key。MaxCompute将对指定列进行Hash运算,按照Hash值分散到各个Bucket中。为避免数据倾斜和热点,并取得较好的并行执行效果,clustered by列适宜选择取值范围大,重复键值少的列。此外,为了达到join优化的目的,也应该考虑选取常用的Join或Aggregation Key,即类似于传统数据库中的主键。

    • sorted by:指定Bucket内字段的排序方式。建议sorted byclustered by保持一致,以取得较好的性能。此外,当指定sorted by子句后,MaxCompute将自动生成索引,并且在查询时利用索引来加快执行。

    • number_of_buckets:指定哈希桶的数量。该值必须填写,且由数据量大小决定。此外,MaxCompute默认支持最多1111个Reducer,所以此处最多只支持1111个哈希桶。您可以使用set odps.stage.reducer.num =<并发数>;来提升这个限制,但最大不得超过4000,否则会影响性能。

      选择哈希桶数目时,请您遵循以下两个原则:

      • 哈希桶大小适中:建议每个Bucket的大小为500 MB左右。例如,分区大小估计为500 GB,初略估算Bucket数目应该设为1000,这样平均每个Bucket大小约为500 MB。对于特别大的表,500 MB的限制可以突破,每个Bucket在2 GB~3 GB左右比较合适。同时,可以结合set odps.stage.reducer.num =<并发数>;来突破1111个桶的限制。

      • 对于join优化场景,去除Shuffle和Sort步骤能显著提升性能。因此要求两个表的哈希桶数目成倍数关系,例如256和512。建议哈希桶的数量统一使用2n,例如512、1024、2048或4096,这样系统可以自动进行哈希桶的分裂和合并,也可以去除Shuffle和Sort的步骤,提升执行效率。

  • Range聚簇表

    • range clustered by:指定范围聚簇列。MaxCompute将对指定列进行分桶运算,按照分桶编号分散到各个Bucket中。

    • sorted by:指定Bucket内字段的排序方式,使用方法与Hash聚簇表相同。

    • number_of_buckets:指定哈希桶的数量。Range聚簇表的Bucket桶数没有Hash聚簇表的2n最佳实践,在数据量分布合理的情况下,任何桶数都可以。Range聚簇表的Bucket数不是必须的,可以省略,此时系统会根据数据量自动决定最佳的Bucket数目。

    • 当Join或Aggregation的对象是Range聚簇表,且Join Key或Group Key是Range Clustering Key或其前缀时,可以通过控制Flag消除数据的重分布,即Shuffle Remove,提升执行效率。您可以通过set odps.optimizer.enable.range.partial.repartitioning=true/false;进行设置,默认关闭。

      说明
      • 聚簇表的优点:

        • 优化Bucket Pruning。

        • 优化Aggregation。

        • 优化存储。

      • 聚簇表的限制:

        • 不支持insert into,只能通过insert overwrite来添加数据。

        • 不支持Tunnel直接Upload到Range聚簇表,因为Tunnel上传数据是无序的。

stored by StorageHandler

可选。

按照外部表数据格式指定StorageHandler。

with serdeproperties (options)

可选。

外部表的授权、压缩、字符解析等相关参数。

osslocation

可选。

外部表数据OSS存储位置,详情请参见创建OSS外部表

tblproperties("transactional"="true")

可选。

设置表为Transactional表。后续可以对Transactional表执行updatedelete操作实现行级更新或删除数据。更多信息,请参见更新或删除数据(UPDATE | DELETE)

Transactional表的使用限制如下:

  • MaxCompute只允许在创建表时设置Transactional属性。已创建的表不允许通过alter table方式修改Transactional属性,执行如下语句会报错:

    alter table not_txn_tbl set tblproperties("transactional"="true");
    --报错。
    FAILED: Catalog Service Failed, ErrorCode: 151, Error Message: Set transactional is not supported
  • 在创建表时,不支持将聚簇表、外部表设置为Transactional表。

  • 不支持MaxCompute内部表、外部表、聚簇表与Transactional表互转。

  • 不支持其他系统的作业(例如Spark on MaxCompute、PAI、Graph)访问Transactional表。

  • 不支持clone tablemerge partition操作。

  • 不支持通过备份与恢复功能备份数据,因此在对Transactional表的重要数据执行updatedeleteinsert overwrite操作前需要手动通过select+insert操作将数据备份至其他表中。

lifecycle

可选。

表的生命周期,仅支持正整数。单位:天。

  • 非分区表:自最后一次修改表数据开始计算,经过days天后数据无改动,则您无需干预此表,MaxCompute会自动回收(类似drop table操作)。

  • 分区表:系统根据各分区的LastModifiedTime判断是否需要回收分区。不同于非分区表,分区表的最后一个分区被回收后,该表不会被删除。生命周期只能设定到表级别,不支持在分区级别设置生命周期。

说明
  • 通过create table [if not exists] <table_name> [lifecycle <days>] as <select_statement>;语句可以再创建一个表,并在建表的同时将数据复制到新表中。但通过该语句创建的表不会复制分区属性,只会把源表的分区列作为目标表的一般列处理,也不会复制源表的生命周期属性。您还可以通过lifecycle参数回收表。

  • 通过create table [if not exists] <table_name> like <existing_table_name> [lifecycle <days>];语句可以再创建一个表,使目标表和源表具有相同的表结构。但通过该语句创建的表不复制数据,也不会复制源表的生命周期属性。您还可以通过lifecycle参数回收表。

使用示例

  • 示例1:创建非分区表test1。

    create table test1 (key STRING);
  • 示例2:创建一张分区表sale_detail。

    create table if not exists sale_detail(
     shop_name     STRING,
     customer_id   STRING,
     total_price   DOUBLE)
    partitioned by (sale_date STRING, region STRING); 
  • 示例3:创建一个新表sale_detail_ctas1,将sale_detail的数据复制到sale_detail_ctas1中,并设置生命周期。

    create table sale_detail_ctas1 lifecycle 10 as select * from sale_detail;

    您可以通过desc extended sale_detail_ctas1;命令查看到表的结构及生命周期等详细信息。

    此处sale_detail是一张分区表,而通过create table ... as select_statement ...语句创建的表sale_detail_ctas1不会复制分区属性,只会把源表的分区列作为目标表的一般列处理。即sale_detail_ctas1是一个含有5列的非分区表。

  • 示例4:创建一个新表sale_detail_ctas2,在select子句中使用常量作为列的值。

    --指定列的名字。
    create table sale_detail_ctas2
    as
    select shop_name, customer_id, total_price, '2013' as sale_date, 'China' as region
    from sale_detail;
    --不指定列的名字。
    create table sale_detail_ctas3
    as
    select shop_name, customer_id, total_price, '2013', 'China' 
    from sale_detail;
    说明

    如果在select子句中使用常量作为列的值,建议您指定列的名字。创建的表sale_detail_ctas3的第四、五列类似于_c4_c5

  • 示例5:创建一个新表sale_detail_like,与sale_detail具有相同的表结构,并设置生命周期。

    create table sale_detail_like like sale_detail lifecycle 10;

    您可以通过desc extended sale_detail_like;命令查看到表的结构及生命周期等详细信息。

    sale_detail_like的表结构与sale_detail完全相同。除生命周期属性外,列名、列注释以及表注释等均相同。但sale_detail中的数据不会被复制到sale_detail_like表中。

  • 示例6:创建使用新数据类型的表test_newtype。

    set odps.sql.type.system.odps2=true;
    CREATE TABLE test_newtype (
        c1 TINYINT
        ,c2 SMALLINT
        ,c3 INT
        ,c4 BIGINT
        ,c5 FLOAT
        ,c6 DOUBLE
        ,c7 DECIMAL
        ,c8 BINARY
        ,c9 TIMESTAMP
        ,c10 ARRAY<MAP<BIGINT,BIGINT>>
        ,c11 MAP<STRING,ARRAY<BIGINT>>
        ,c12 STRUCT<s1:STRING,s2:BIGINT>
        ,c13 VARCHAR(20))
    LIFECYCLE 1
    ;
  • 示例7:创建Hash聚簇非分区表t1。

    create table t1 (a STRING, b STRING, c BIGINT) clustered by (c) sorted by (c) into 1024 buckets; 
  • 示例8:创建Hash聚簇分区表t2。

    create table t2 (a STRING, b STRING, c BIGINT) partitioned by (dt STRING) clustered by (c) sorted by (c) into 1024 buckets; 
  • 示例9:创建Range聚簇非分区表t3。

    create table t3 (a STRING, b STRING, c BIGINT) range clustered by (c) sorted by (c) into 1024 buckets;
  • 示例10:创建Range聚簇分区表t4。

    create table t4 (a STRING, b STRING, c BIGINT) partitioned by (dt STRING) range clustered by (c) sorted by (c); 
  • 示例11:创建Transactional非分区表t5。

    create table t5(id bigint) tblproperties("transactional"="true");
  • 示例12:创建Transactional分区表t6。

    create table if not exists t6(id bigint) partitioned by(ds string) tblproperties ("transactional"="true");

相关命令

  • ALTER TABLE:修改表操作。

  • TRUNCATE:将指定表中的数据清空。

  • DROP TABLE:删除分区表或非分区表。

  • DESC TABLE/VIEW:查看MaxCompute内部表、视图、物化视图、外部表、聚簇表或Transactional表的信息。

  • SHOW:查看表的SQL DDL语句、列出项目下所有的表和视图或列出一张表中的所有分区。