MaxCompute支援在資料寫入時自動擷取寫入時間,並結合使用者指定的時間計算函數(TRUNC_TIME),根據計算結果產生分區列的值,從而實現對錶的分區。這種基於資料寫入時間的自動分區表又稱為Ingestion Time Partition表,本文將介紹基於資料寫入時間的自動分區表的使用方法。
功能介紹
MaxCompute支援普通分區表和自動分區表(AUTO PARTITION)兩種分區表類型,可根據不同情境下預期的分區列產生方式,選擇不同的分區表類型。詳情請參見分區表概述。
使用Ingestion Time Partition表時,需要指定一個名為_partitiontime、資料類型為時間類型的列。系統會按照一定的時間粒紋,對每行資料的寫入時間進行截取(如:按小時、按天、按月、按年),然後自動產生_partitiontime列值。
例如,使用者建立了一個按小時截取產生分區的Ingestion Time Partition表,並在以下時間寫入資料:
資料寫入時間(UTC+8) | 產生的 _PARTITIONTIME列(TIMESTAMP類型) | 產生的分區(STRING類型) |
2025-06-18 17:22:00 | 2025-06-18 17:00:00 | 2025-06-18 09:00:00 |
2025-06-18 17:40:00 | 2025-06-18 17:00:00 | 2025-06-18 09:00:00 |
2025-06-18 18:31:00 | 2025-06-18 18:00:00 | 2025-06-18 10:00:00 |
上述樣本中,Ingestion Time Partition表指定按小時截取產生分區,因此,_partitiontime列會根據資料寫入時間進行截取並產生對應的值,並將該值轉換為UTC時間後的STRING類型值,作為資料所在的分區。
使用限制
基於資料寫入時間的自動分區表當前僅支援一個分區列,且不支援多級分區。
基於資料寫入時間的自動分區表的分區列,欄位類型預設為STRING,不支援修改。
基於時間計算函數和資料寫入時間的Auto Partition能力僅在基於MaxCompute SQL寫入時支援,不支援其他資料寫入方式如Flink Connector。
按照資料寫入時間進行截斷時,當前僅支援TRUNC_TIME函數,該函數會將本地時間轉換為UTC時間再進行截斷。因此最終產生的STRING類型分區列的值會受到時區影響。建議執行
SET odps.sql.timezone=UTC;語句調整專案的本地時區為UTC時區。
使用說明
建立Ingestion Time Partition表
文法結構
建立基於資料寫入時間的自動分區表。
CREATE [OR REPLACE] TABLE [IF NOT EXISTS] <table_name> (_partitiontime <data_type>, <col_name><data_type>... )
[COMMENT <table_comment>]
AUTO PARTITIONED BY (<auto_partition_expression> [AS <auto_partition_column_name>]);
TBLPROPERTIES('ingestion_time_partition'='true');參數說明如下:
參數 | 是否必填 | 描述 |
table_name | 是 | 待建立的表名。 |
_partitiontime | 是 | 按資料寫入時間截取產生的時間偽列,列名不支援修改,資料類型僅支援TIMESTAMP、TIMESTAMP_NTZ。 |
col_name | 是 | 列名。 |
data_type | 是 | 列資料類型。 |
table_comment | 否 | 表注釋。 |
TBLPROPERTIES('ingestion_time_partition'='true') | 是 | 指定所建立的表為基於資料寫入時間的自動分區表(Ingestion Time Partition表),按資料寫入時間產生分區列。 |
auto_partition_expression | 是 | 定義如何進行分區列計算的運算式。當前僅支援使用TRUNC_TIMEFunction Compute 說明 當建立基於資料寫入時間的自動分區表時,系統會自動擷取資料寫入時間,並通過TRUNC_TIME函數對寫入時間進行截取,從而產生分區列的值。 |
auto_partition_column_name | 否 | 產生分區列的列名,若未指定分區列的列名,則系統會以 說明 使用分區運算式進行分區計算後,會根據計算結果產生一個STRING類型的分區列,列的類型和列的取值均不支援直接操作。 |
使用樣本
樣本1
建立一張按小時分區,表名為
ingestion_sale_detail_hourly的Ingestion Time Partition表,表中指定一個TIMESTAMP類型時間偽列_partitiontime。當資料寫入時,系統會自動擷取資料寫入時間,並根據DDL語句中按小時作為截取粒度產生_partitiontime列的值,然後基於計算結果產生表的分區sale_time。-- 表建立完成後,當資料寫入時系統會自動擷取資料寫入時間,按小時為粒度進行截取計算_partitiontime,並產生名為sale_time的分區列,並根據該分區列進行表的分區 CREATE TABLE IF NOT EXISTS ingestion_sale_detail_hourly( shop_name STRING, total_price DOUBLE, _partitiontime TIMESTAMP) AUTO PARTITIONED BY (TRUNC_TIME(_partitiontime, 'hour') AS sale_time) TBLPROPERTIES('ingestion_time_partition'='true');上述建立的
ingestion_sale_detail_hourly表包含4列,其中sale_time是自動產生的一個STRING類型的分區列。可執行DESC ingestion_sale_detail_hourly;語句查看錶資訊,返回結果樣本如下:+------------------------------------------------------------------------------------+ | Owner: ALIYUN$test**** | | Project: xxxxxxx | | Schema: default | | TableComment: | +------------------------------------------------------------------------------------+ | CreateTime: 2025-06-16 14:59:40 | | LastDDLTime: 2025-06-16 14:59:40 | | LastModifiedTime: 2025-06-16 14:59:40 | +------------------------------------------------------------------------------------+ | InternalTable: YES | Size: 0 | +------------------------------------------------------------------------------------+ | Native Columns: | +------------------------------------------------------------------------------------+ | Field | Type | Label | Comment | +------------------------------------------------------------------------------------+ | shop_name | string | | | | | total_price | double | | | | _partitiontime | timestamp | | | +------------------------------------------------------------------------------------+ | Partition Columns: | +------------------------------------------------------------------------------------+ | sale_time | string | | +------------------------------------------------------------------------------------+樣本2
建立一張按天分區,表名為
ingestion_sale_detail_daily的Ingestion Time Partition表。當表的分區產生截取粒度為按天時,除了_partitiontime之外,會額外產生一個DATE類型的偽列_partitiondate。CREATE TABLE IF NOT EXISTS ingestion_sale_detail_daily( shop_name STRING, total_price DOUBLE, _partitiontime TIMESTAMP) AUTO PARTITIONED BY (TRUNC_TIME(_partitiontime, 'day') AS sale_date) TBLPROPERTIES('ingestion_time_partition'='true');說明可通過
SELECT *, _partitiondate FROM ingestion_sale_detail_daily;命令查看偽列_partitiondate。如需查看Ingestion Time Partition分區列的分區產生計算邏輯,可以通過SHOW CREATE TABLE進行查看。
寫入Ingestion Time Partition表
當使用SQL語句向Ingestion Time Partition表中寫入資料時,支援指定_partitiontime時間偽列的值,但需保證_partitiontime列值的時間截取粒度與建表語句中定義的一致。
若不指定_partitiontime,則系統會自動擷取資料寫入MaxCompute的時間,結合使用者指定的時間計算函數,根據計算結果產生_partitiontime時間偽列和分區列的值,對資料進行分區。
樣本如下:
下述樣本基於使用樣本中已建立的ingestion_sale_detail_hourly和ingestion_sale_detail_daily表,進行資料寫入。
樣本1
插入資料時,不指定
_partitiontime時間偽列的值。INSERT INTO ingestion_sale_detail_hourly (shop_name,total_price) VALUES ('shanghai_shop',10001.1), ('chongqin_shop',20002.2), ('hangzhou_shop',30003.3), ('shenzhen_shop',40004.4);樣本2
插入資料時,指定
_partitiontime時間偽列的值,需保證寫入的_partitiontime列值與分區產生的指定時間截取粒度(hour)一致。正確樣本:指定
_partitiontime列的值為'2025-06-15 14:00:00'。INSERT INTO ingestion_sale_detail_hourly (shop_name,total_price,_partitiontime) VALUES ('beijing_shop',50005.5,TIMESTAMP '2025-06-15 14:00:00'), ('chengdu_shop',60006.6,TIMESTAMP '2025-06-14 05:00:00');錯誤樣本:指定
_partitiontime列的值為'2025-06-15 14:30:00',與分區產生的按小時截取粒度不一致。INSERT INTO ingestion_sale_detail_hourly (shop_name,total_price,_partitiontime) VALUES ('beijing_shop',50005.5,TIMESTAMP '2025-06-15 14:30:00');返回的報錯資訊如下:
FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: SQL Runtime Unretryable Error: ODPS-0121095:Invalid argument - illegal ingestion time: 2025-06-15 14:30:00
樣本3
當分區產生的截取粒度為按天時,仍然僅支援指定
_partitiontime時間偽列的值,不支援指定_partitiondate日期偽列值。正確樣本:指定
_partitiontime列的值為'2025-06-18 00:00:00'。INSERT INTO ingestion_sale_detail_daily (shop_name,total_price,_partitiontime) VALUES ('beijing_shop',50005.5,TIMESTAMP '2025-06-18 00:00:00');錯誤樣本:
指定
_partitiontime列的值為'2025-06-15 14:00:00',與分區產生的按天截取粒度不一致。INSERT INTO ingestion_sale_detail_daily (shop_name,total_price,_partitiontime) VALUES ('beijing_shop',50005.5,TIMESTAMP '2025-06-18 14:00:00');返回的報錯資訊如下:
FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: SQL Runtime Unretryable Error: ODPS-0121095:Invalid argument - illegal ingestion time: 2025-06-18 14:00:00直接指定
_partitiondate偽列的值。INSERT INTO ingestion_sale_detail_daily (shop_name,total_price,_partitiondate) VALUES ('beijing_shop',50005.5,DATE '2025-06-15');返回的錯誤資訊如下:
FAILED: ODPS-0130071:[1,64] Semantic analysis exception - column _partitiondate cannot be resolved; Did you mean _partitiontime ?
查詢Ingestion Time Partition表
執行
SELECT *的查詢語句時,系統預設不顯示_partitiontime或_partitiondate偽列及產生的分區列。若希望顯示,則需在語句中顯式指定對應的列,例如SELECT *, _partitiontime FROM xxx;。對於按小時、按月、按年粒度進行截取產生分區的表,可以使用時間類型的偽列
_partitiontime進行查詢過濾和分區裁剪。Ingestion Time Partition表作為一種特殊的自動分區表,支援的分區裁剪能力與普通自動分區表一致,詳情請參見基於時間計算函數的自動分區表。
樣本如下:
下述樣本基於使用樣本中已建立的ingestion_sale_detail_hourly和ingestion_sale_detail_daily表,進行資料查詢。
樣本1
執行
SELECT *的查詢語句時,系統預設不顯示_partitiontime或_partitiondate偽列及產生的分區列。SELECT * FROM ingestion_sale_detail_hourly; -- 返回結果 +------------+-------------+ | shop_name | total_price | +---------------+-------------+ | shanghai_shop | 10001.1 | | chongqin_shop | 20002.2 | | hangzhou_shop | 30003.3 | | shenzhen_shop | 40004.4 | | chengdu_shop | 60006.6 | | beijing_shop | 50005.5 | +---------------+-------------+樣本2
查詢時指定顯示
_partitiontime或_partitiondate偽列及產生的分區列,其中sale_time和sale_date是在建立該表時指定的產生分區列的列名。說明本樣本中通過
set odps.sql.timezone=Asia/Shanghai;設定專案本地時區為東八區時區,在TRUNC_TIME截取產生的分區值時,會受到時區影響。查詢按小時分區的
ingestion_sale_detail_hourly表。SELECT * ,_partitiontime,sale_time FROM ingestion_sale_detail_hourly; --返回結果如下 +---------------+-------------+---------------------+---------------------+ | shop_name | total_price | _partitiontime | sale_time | +---------------+-------------+---------------------+---------------------+ | shanghai_shop | 10001.1 | 2025-06-18 15:00:00 | 2025-06-18 07:00:00 | | chongqin_shop | 20002.2 | 2025-06-18 15:00:00 | 2025-06-18 07:00:00 | | hangzhou_shop | 30003.3 | 2025-06-18 15:00:00 | 2025-06-18 07:00:00 | | shenzhen_shop | 40004.4 | 2025-06-18 15:00:00 | 2025-06-18 07:00:00 | | beijing_shop | 50005.5 | 2025-06-15 14:00:00 | 2025-06-15 06:00:00 | | chengdu_shop | 60006.6 | 2025-06-14 05:00:00 | 2025-06-13 21:00:00 | +---------------+-------------+---------------------+---------------------+查詢按天分區的
ingestion_sale_detail_daily表。SELECT * ,_partitiontime,_partitiondate,sale_date FROM ingestion_sale_detail_daily; --返回結果如下 +--------------+-------------+---------------------+----------------+-----------+ | shop_name | total_price | _partitiontime | _partitiondate | sale_date | +--------------+-------------+---------------------+----------------+-----------+ | beijing_shop | 50005.5 | 2025-06-18 00:00:00 | 2025-06-18 | 2025-06-18| +--------------+-------------+---------------------+----------------+-----------+