建立非分區表、分區表、外部表格或聚簇表。
限制條件
分區表的分區層級不能超過6級。例如某張表以日期為分區列,分區層級為
年/月/周/日/時/分
。一張表允許的分區個數支援按照具體的專案配置,預設為6萬個。
更多表的限制條件,請參見SQL使用限制項。
命令格式
建立內部表
CREATE [OR REPLACE] TABLE [IF NOT EXISTS] <table_name> (
<col_name> <data_type>, ... )
[comment <table_comment>]
[PATITIONED BY (<col_name> <data_type> [comment <col_comment>], ...)];
建立聚簇表
CREATE TABLE [IF NOT EXISTS] <table_name> (
<col_name> <data_type>, ... )
[CLUSTERED BY | RANGE CLUSTERED BY (<col_name> [, <col_name>, ...])
[SORTED BY (<col_name> [ASC | DESC] [, <col_name> [ASC | DESC] ...])]
INTO <number_of_buckets> buckets];
建立外部表格
以OSS外部表格為例,通過內建文本資料解析器建立外部表格。
CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name> (
<col_name> <data_type>, ... )
STORED AS '<file_format>'
[WITH SERDEPROPERTIES (options)]
LOCATION '<oss_location>';
建立表並指定表類型
指定表為Transactional表。後續可以對該表執行更新或刪除表資料操作,但是Transactional表有部分使用限制,請根據需求建立。
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] <table_name> ( <col_name <data_type> [NOT NULL] [DEFAULT <default_value>] [comment <col_comment>], ... [PRIMARY KEY (<pk_col_name>[, <pk_col_name2>, ...] )]) [comment <table_comment>] [TBLPROPERTIES ("transactional"="true")];
指定表為Delta Table表。結合PRIMARY KEY,後續可以做upsert、增量查詢和Time Travel等操作。
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] <table_name> ( <col_name <data_type> [NOT NULL] [DEFAULT <default_value>] [comment <col_comment>], ... [PRIMARY KEY (<pk_col_name>[, <pk_col_name2>, ...] )]) [comment <table_comment>] [TBLPROPERTIES ("transactional"="true" [, "write.bucket.num" = "N", "acid.data.retain.hours"="hours"...])] [lifecycle <days>];
基於已存在表建立新表
基於已存在的表建立新表並複製資料,但不複製分區屬性。支援外部表格和湖倉一體外部項目中的表。
CREATE TABLE [IF NOT EXISTS] <table_name> [LIFECYCLE <days>] AS <select_statement>;
基於已存在的表建立具備相同結構的新表,但不複製資料。支援外部表格和湖倉一體外部項目中的表。
CREATE TABLE [IF NOT EXISTS] <table_name> [LIFECYCLE <days>] LIKE <existing_table_name>;
參數說明
通用參數
參數 | 是否必填 | 說明 | 備忘 |
OR REPLACE | 否 | 若<table_name>已經存在,則對現有表使用DROP TABLE,然後建立具有相同名稱的新表進行替換。 | 等效於執行如下兩條命令:
說明 使用限制:CREATE OR REPLACE TABLE暫不支援和以下文法共用。
|
EXTERNAL | 否 | 建立的表為外部表格。 | 無 |
IF NOT EXISTS | 否 | 確認庫中是否已存在建立表名。 | 如果不指定IF NOT EXISTS選項而存在同名表,會報錯。如果指定IF NOT EXISTS,只要存在同名表,即使原表結構與要建立的目標表結構不一致,均返回成功。已存在的同名表的中繼資料資訊不會被改動。 |
table_name | 是 | 表名。 | 表名大小寫不敏感,不能有特殊字元,只能包含a~z、A~Z、數字和底線(_)。建議以字母開頭,名稱的長度不超過128位元組,否則報錯。 |
PRIMARY KEY(pk) | 否 | 表的主鍵。 | 可以定義一個或多個列作為主鍵,表示這些列的組合在表中必須唯一,文法遵循標準SQL primary key文法,pk列必須設定NOT NULL,不允許修改。 |
col_name | 是 | 表的列名。 | 列名大小寫不敏感,不能有特殊字元,只能包含a~z、A~Z、數字、底線(_)或中文。建議以字母開頭,名稱的長度不超過128位元組,否則報錯。 |
col_comment | 否 | 列名的注釋。 | 注釋內容為長度不超過1024位元組的有效字串,否則報錯。 |
data_type | 是 | 列的資料類型。 | 包含BIGINT、DOUBLE、BOOLEAN、DATETIME、DECIMAL和STRING等多種資料類型,詳情請參見資料類型版本說明。 |
NOT NULL | 否 | 禁止該列的值為NULL。 | 更多修改非空屬性資訊,請參見分區操作。 |
default_value | 否 | 列的預設值。 | 當 說明 當前預設值不支援函數,例如 |
table_comment | 否 | 表注釋。 | 注釋內容為長度不超過1024位元組的有效字串,否則報錯。 |
LIFECYCLE | 否 | 表的生命週期。 | 僅支援正整數。單位為天。
|
分區表參數
參數 | 是否必填 | 說明 | 備忘 |
PARTITIONED BY | 是 | 指定分區表的分區欄位。 | 無 |
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位元組的有效字串,否則報錯。 |
分區值不能包含雙位元組字元(如中文),必須以字母開頭,包含字母、數字和允許的字元,長度不超過255位元組。允許的字元包括空格、冒號(:)、底線(_)、貨幣符號($)、井號(#)、英文句點(.)、驚嘆號(!)和at(@),其他字元的行為未定義,例如逸出字元\t
、\n
和/
。
聚簇表參數
聚簇表分為Hash聚簇表和Range聚簇表兩種。
HASH聚簇表
參數 | 是否必填 | 說明 | 備忘 |
CLUSTERED BY | 是 | 指定Hash Key。 | MaxCompute將對指定列進行Hash運算,按照Hash值分散到各個Bucket中。為避免資料扭曲和熱點,並取得較好的並存執行效果, |
SORTED BY | 是 | 指定Bucket內欄位的排序方式。 | 建議SORTED BY和CLUSTERED BY保持一致,以取得較好的效能。此外,當指定SORTED BY子句後,MaxCompute將自動產生索引,並且在查詢時利用索引來加快執行。 |
number_of_buckets | 是 | 指定雜湊桶的數量。 | 該值必須填寫,且由資料量大小決定。此外,MaxCompute預設支援最多1111個Reducer,所以此處最多隻支援1111個雜湊桶。您可以使用 |
選擇雜湊桶數目時,請您遵循以下兩個原則:
雜湊桶大小適中:建議每個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上傳資料是無序的。
不支援備份恢複功能。
外部表格參數
本樣本以OSS外部表格建立參數為例。更多外部表格建立,詳情請參見外部資料源。
參數 | 是否必填 | 說明 |
| 是 | 按照外部表格資料格式指定file_format。 |
| 否 | 外部表格的授權、壓縮、字元解析等相關參數。 |
oss_location | 是 | 外部表格資料OSS儲存位置,詳情請參見建立OSS外部表格。 |
Transaction Table與Delta Table表參數
Transaction Table表參數
參數 | 是否必填 | 說明 |
TBLPROPERTIES(transactional"="true") | 是 | 設定表為Transactional表。後續可以對Transactional表執行 |
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表互轉。
不支援自動合并Transactional表檔案,需要手動執行合併作業,詳情請參見合并Transactional表檔案。
不支援
merge partition
操作。其他系統的作業訪問Transactional表有一些限制,例如Graph不支援讀寫;Spark、PAI只支援讀,不支援寫。
在對Transactional表的重要資料執行
update
、delete
或insert overwrite
操作前需要手動通過select
+insert
操作將資料備份至其他表中。
Delta Table表參數
Delta Table是一種可支援近即時讀寫,增量儲存和讀寫,即時更新等能力的表格式,目前只支援主鍵表。
參數 | 是否必填 | 說明 | 備忘 |
PRIMARY KEY(PK) | 是 | 建立Delta Table主鍵表時必填,可包含多列。 | 文法遵循標準SQL primary key文法,PK列必須設定not null,不允許修改。 設定後,後續表資料會根據PK列進行去重,Unique約束在單個partition範圍內有效,或非分區表內有效。 |
transactional | 是 | 建立Delta Table類型表時必填,必須設定為true。 | 表示符合MaxCompute的ACID表的事務特性,採用MVCC交易管理模式,保證快照隔離等級。 |
write.bucket.num | 否 | 預設取值為16,取值範圍為 | 表示每個partition或者非分區表的分桶數量,也表示資料寫入的並發節點數量。分區表支援修改,新分區預設生效,非分區表不支援修改。該參數用法可參考如下建議:
|
acid.data.retain.hours | 否 | 預設取值為24,取值範圍為 | 表示TimeTravel可查詢資料歷史狀態的時間範圍(單位為小時)。若需要超過168小時(7天)的長時間TimeTravel歷史回溯,可聯絡MaxCompute支援人員。
|
acid.incremental.query.out.of.time.range.enabled | 否 | 預設 | True表示增量查詢指定的endTimestamp可大於表最大的資料Commit Time,在endTimestamp大於目前時間情境下,使用者多次查詢可能得到不同的結果,因為可能有新的資料插入。支援修改表的此參數取值。 |
acid.write.precombine.field | 否 | 可以指定一個列的名稱,且只能指定一個。 | 如果指定了列名,在同一提交的檔案處理中,系統會結合主鍵(PK)列對資料進行去重處理,確保資料的唯一性和一致性。 說明 當一次性提交的資料量超過128 M時,會導致產生多個檔案,該參數對多個檔案不適用。 |
Delta Table其他通用參數的設定要求。
LIFECYCLE: 表生命週期必須大於等於Time Travel可查詢的生命週期,即
lifecycle >= acid.data.retain.hours / 24
。建立表時會做檢查,不符合會報錯。其他不支援的特性:不支援設定CLUSTER BY、EXTERNAL外表和CREATE TABLE AS。
其他使用限制:
當前不支援除MaxCompute SQL外的其他引擎直接操作Delta Table。
存量普通表不支援修改為Delta Table。
不支援對Delta Table主鍵表的PK列做表結構變更。
基於已有資料表建表參數
通過
CREATE TABLE [IF NOT EXISTS] <table_name> [LIFECYCLE <days>] AS <select_statement>;
語句可以再建立一個表,並在建表的同時將資料複製到新表中。但通過該語句建立的表不會複製分區屬性,只會把源表的分區列作為目標表的一般列處理,也不會複製源表的生命週期屬性。
您還可以通過lifecycle參數回收表。同時也支援建立內部表複製外部表格的資料。
通過
CREATE TABLE [IF NOT EXISTS] <table_name> [LIFECYCLE <days>] LIKE <existing_table_name>;
語句可以再建立一個表,使目標表和源表具有相同的表結構。但通過該語句建立的表不複製資料,也不會複製源表的生命週期屬性。
您還可以通過lifecycle參數回收表。同時也支援建立內部表複製外部表格的結構。
使用樣本
建立非分區表
CREATE TABLE test1 (key STRING);
建立分區表
建立一張分區表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);
建立新表替換原表
建立原有表
mytable
,並寫入資料。CREATE OR REPLACE TABLE my_table(a bigint); INSERT INTO my_table(a) VALUES (1),(2),(3);
使用OR REPLACE建立新的同名表,並修改欄位。
CREATE OR REPLACE TABLE my_table(b string);
查詢
my_table
表,返回結果如下。+------------+ | b | +------------+ +------------+
以下為非法的SQL語句:
CREATE OR REPLACE TABLE IF NOT EXISTS my_table(b STRING);
CREATE OR REPLACE TABLE my_table AS SELECT;
CREATE OR REPLACE TABLE my_table LIKE newtable;
建立新表並複製已有表資料至新表
建立新表,將已有表資料複製到新表,並設定生命週期。
-- 建立一個新表sale_detail_ctas1,將sale_detail的資料複製到sale_detail_ctas1中,並設定生命週期。
SET odps.sql.allow.fullscan=true;
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列的非分區表。
建立新表並將SELECT語句常量作為列值
如果在SELECT
子句中使用常量作為列的值,建議您指定列的名字。建立的表sale_detail_ctas3的第四、五列類似於_c4
、_c5
。
指定列的名字。
SET odps.sql.allow.fullscan=true; CREATE TABLE sale_detail_ctas2 AS SELECT shop_name, customer_id, total_price, '2013' AS sale_date, 'China' AS region FROM sale_detail;
不指定列的名字。
SET odps.sql.allow.fullscan=true; CREATE TABLE sale_detail_ctas3 AS SELECT shop_name, customer_id, total_price, '2013', 'China' FROM 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表中。
建立新表與外部表格結構相同
-- 建立一個新表mc_oss_extable_orc_like,與外部表格mc_oss_extable_orc具有相同的表結構。
CREATE TABLE mc_oss_extable_orc_like LIKE mc_oss_extable_orc;
您可以通過DESC mc_oss_extable_orc_like;
命令查看錶結構等詳細資料。
+------------------------------------------------------------------------------------+
| Owner: ALIYUN$****@***.aliyunid.com | Project: max_compute_7u************yoq |
| TableComment: |
+------------------------------------------------------------------------------------+
| CreateTime: 2022-08-11 11:10:47 |
| LastDDLTime: 2022-08-11 11:10:47 |
| LastModifiedTime: 2022-08-11 11:10:47 |
+------------------------------------------------------------------------------------+
| InternalTable: YES | Size: 0 |
+------------------------------------------------------------------------------------+
| Native Columns: |
+------------------------------------------------------------------------------------+
| Field | Type | Label | Comment |
+------------------------------------------------------------------------------------+
| id | string | | |
| name | string | | |
+------------------------------------------------------------------------------------+
建立使用新資料類型的表
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;
建立Hash聚簇表
非分區表
CREATE TABLE t1 (a STRING, b STRING, c BIGINT) CLUSTERED BY (c) SORTED BY (c) INTO 1024 buckets;
分區表
CREATE TABLE t2 (a STRING, b STRING, c BIGINT) PARTITIONED BY (dt STRING) CLUSTERED BY (c) SORTED BY (c) into 1024 buckets;
建立Range聚簇表
非分區表
CREATE TABLE t3 (a STRING, b STRING, c BIGINT) RANGE CLUSTERED BY (c) SORTED BY (c) INTO 1024 buckets;
分區表
CREATE TABLE t4 (a STRING, b STRING, c BIGINT) PARTITIONED BY (dt STRING) RANGE CLUSTERED BY (c) SORTED BY (c);
建立Transactional表
非分區表
CREATE TABLE t5(id bigint) tblproperties("transactional"="true");
分區表
CREATE TABLE IF NOT EXISTS t6(id bigint) PARTITIONED BY (ds string) tblproperties ("transactional"="true");
建立Delta Table表
建立Delta Table表
CREATE TABLE mf_tt (pk bigint NOT NULL PRIMARY KEY, val bigint) tblproperties ("transactional"="true");
建立Delta Table表,設定主要表屬性。
CREATE TABLE mf_tt2 ( pk bigint NOT NULL, pk2 bigint NOT NULL, val bigint, val2 bigint, PRIMARY KEY (pk, pk2) ) tblproperties ( "transactional"="true", "write.bucket.num" = "64", "acid.data.retain.hours"="120" ) lifecycle 7;
建立非分區表並為欄位指定預設值
CREATE TABLE test_default(
tinyint_name tinyint NOT NULL default 1Y,
smallint_name SMALLINT NOT NULL DEFAULT 1S,
int_name INT NOT NULL DEFAULT 1,
bigint_name BIGINT NOT NULL DEFAULT 1,
binary_name BINARY ,
float_name FLOAT ,
double_name DOUBLE NOT NULL DEFAULT 0.1,
decimal_name DECIMAL(2, 1) NOT NULL DEFAULT 0.0BD,
varchar_name VARCHAR(10) ,
char_name CHAR(2) ,
string_name STRING NOT NULL DEFAULT 'N',
boolean_name BOOLEAN NOT NULL DEFAULT TRUE
);
建立內部表並複製外部分區表資料
內部表不包含分區屬性。
建立OSS外部表格和MaxCompute內部表。
-- 建立oss外部表格並插入資料。 CREATE EXTERNAL table max_oss_test(a int, b int, c int) stored AS TEXTFILE location "oss://oss-cn-hangzhou-internal.aliyuncs.com/<bucket_name>"; INSERT INTO max_oss_test VALUES (101, 1, 20241108), (102, 2, 20241109), (103, 3, 20241110); SELECT * FROM max_oss_test; -- 結果 a b c 101 1 20241108 102 2 20241109 103 3 20241110 -- 使用create table as建立內部表 CREATE TABLE from_exetbl_oss AS SELECT * FROM max_oss_test; -- 查詢建立內部表 SELECT * FROM from_exetbl_oss; -- 返回結果,全表資料都有 a b c 101 1 20241108 102 2 20241109 103 3 20241110
執行
DESC from_exetbl_as_par;
查詢內部表結構。返回結果如下。+------------------------------------------------------------------------------------+ | Owner: ALIYUN$*********** | | Project: ***_*****_*** | | TableComment: | +------------------------------------------------------------------------------------+ | CreateTime: 2023-01-10 15:16:33 | | LastDDLTime: 2023-01-10 15:16:33 | | LastModifiedTime: 2023-01-10 15:16:33 | +------------------------------------------------------------------------------------+ | InternalTable: YES | Size: 919 | +------------------------------------------------------------------------------------+ | Native Columns: | +------------------------------------------------------------------------------------+ | Field | Type | Label | Comment | +------------------------------------------------------------------------------------+ | a | string | | | | b | string | | | | c | string | | | +------------------------------------------------------------------------------------+
內部表包含分區屬性。
建立內部表
from_exetbl_like
。-- MaxCompute側查詢湖倉一體外部表格 SELECT * FROM max_oss_test; -- 返回結果 a b c 101 1 20241108 102 2 20241109 103 3 20241110 -- 使用create table like建立內部表 CREATE TABLE from_exetbl_like LIKE max_oss_test; -- 查詢建立內部表 SELECT * FROM from_exetbl_like; -- 返回結果,只有表結構出現 a b c
執行
DESC from_exetbl_like;
查詢內部表結構。返回結果如下。+------------------------------------------------------------------------------------+ | Owner: ALIYUN$************ | | Project: ***_*****_*** | | TableComment: | +------------------------------------------------------------------------------------+ | CreateTime: 2023-01-10 15:09:47 | | LastDDLTime: 2023-01-10 15:09:47 | | LastModifiedTime: 2023-01-10 15:09:47 | +------------------------------------------------------------------------------------+ | InternalTable: YES | Size: 0 | +------------------------------------------------------------------------------------+ | Native Columns: | +------------------------------------------------------------------------------------+ | Field | Type | Label | Comment | +------------------------------------------------------------------------------------+ | a | string | | | | b | string | | | +------------------------------------------------------------------------------------+ | Partition Columns: | +------------------------------------------------------------------------------------+ | c | string | | +------------------------------------------------------------------------------------+
相關命令
ALTER TABLE:修改表操作。
TRUNCATE:將指定表中的資料清空。
DROP TABLE:刪除分區表或非分區表。
DESC TABLE/VIEW:查看MaxCompute內部表、視圖、物化視圖、外部表格、聚簇表或Transactional表的資訊。
SHOW:查看錶的SQL DDL語句、列出專案下所有的表和視圖或列出一張表中的所有分區。