With regular partitioned tables, you must create each partition before writing data and manually calculate the correct partition value for every row. AUTO PARTITION tables eliminate this overhead: you define a time computing function at table creation, and MaxCompute automatically generates the partition column value for each row based on that function when data is written.
This document covers auto-partitioned tables that derive partition values from a time computing function applied to an existing time/date column. For auto-partitioning based on data write time instead, see Auto-partitioned tables based on data write time. For an overview of all partitioned table types, see Partitioned table overview.
Limitations
-
Only one partition column is supported per table. Multi-level partitioning is not supported.
-
The partition column is automatically generated based on the partition expression defined at table creation. Its data type is always STRING and cannot be changed.
-
Auto-partitioning is supported only when writing data with MaxCompute SQL. Other write methods, such as Flink connectors, are not supported.
Create an auto-partitioned table
Syntax
CREATE [OR REPLACE] TABLE [IF NOT EXISTS] <table_name> (<col_name> <data_type>, ...)
[COMMENT <table_comment>]
AUTO PARTITIONED BY (<auto_partition_expression> [AS <auto_partition_column_name>]);
Parameters
| Parameter | Required | Description |
|---|---|---|
table_name |
Yes | The name of the table to create. |
col_name |
Yes | The column name. |
data_type |
Yes | The column data type. Supported time/date types for the partition source column: DATE, DATETIME, TIMESTAMP, TIMESTAMP_NTZ. |
table_comment |
No | A comment for the table. |
auto_partition_expression |
Yes | The expression defining how partition column values are calculated. Only the TRUNC_TIME function is supported. The resulting partition column is always STRING type, and its values do not support direct operations. |
auto_partition_column_name |
No | The name of the generated partition column. If omitted, the system uses _pt_col_0_ and increments the suffix (_pt_col_1_, _pt_col_2_, and so on) until an unused name is found. |
Examples
Example 1: Partition by day using a TIMESTAMP column (default partition column name)
Create an auto-partitioned table sale_detail with a TIMESTAMP column sale_time, partitioned by day:
CREATE TABLE IF NOT EXISTS sale_detail(
shop_name STRING,
total_price DOUBLE,
sale_time TIMESTAMP)
AUTO PARTITIONED BY (TRUNC_TIME(sale_time, 'day'));
The table contains four columns: shop_name, total_price, sale_time, and _pt_col_0_. The _pt_col_0_ column is the automatically generated partition column with STRING type.
Run DESC sale_detail; to view the table structure:
+------------------------------------------------------------------------------------+
| Owner: ALIYUN$*** |
| Project: *** |
| TableComment: |
+------------------------------------------------------------------------------------+
| CreateTime: 2025-06-26 11:21:55 |
| LastDDLTime: 2025-06-26 11:21:55 |
| LastModifiedTime: 2025-06-26 11:21:55 |
+------------------------------------------------------------------------------------+
| InternalTable: YES | Size: 0 |
+------------------------------------------------------------------------------------+
| Native Columns: |
+------------------------------------------------------------------------------------+
| Field | Type | Label | Comment |
+------------------------------------------------------------------------------------+
| shop_name | string | | |
| total_price | double | | |
| sale_time | timestamp | | |
+------------------------------------------------------------------------------------+
| Partition Columns: |
+------------------------------------------------------------------------------------+
| _pt_col_0_ | string | |
+------------------------------------------------------------------------------------+
To view the partition generation expression for an AUTO PARTITION column, use SHOW CREATE TABLE.
Example 2: Partition by day with an explicit partition column name
Specify an explicit partition column name sale_date:
CREATE TABLE IF NOT EXISTS sale_detail2(
shop_name STRING,
total_price DOUBLE,
sale_time TIMESTAMP)
AUTO PARTITIONED BY (TRUNC_TIME(sale_time, 'day') AS sale_date);
Example 3: Simplified syntax for DATE columns
When the source column is DATE type and the truncation granularity is day, you can omit TRUNC_TIME:
-- Full syntax
CREATE TABLE IF NOT EXISTS sale_detail3(
shop_name STRING,
total_price DOUBLE,
sale_date DATE)
AUTO PARTITIONED BY (TRUNC_TIME(sale_date, 'day'));
-- Simplified syntax (equivalent)
CREATE TABLE IF NOT EXISTS sale_detail3(
shop_name STRING,
total_price DOUBLE,
sale_date DATE)
AUTO PARTITIONED BY (sale_date);
The simplified syntax only supports DATE type. DATETIME, TIMESTAMP, and TIMESTAMP_NTZ are not supported.
Write data to an auto-partitioned table
When you write data using MaxCompute SQL, the system calculates the partition column value for each row based on the partition expression defined at table creation. Partition values cannot be specified explicitly.
Example: Write data to `sale_detail2`
-- Set the project time zone to UTC+8 (Asia/Shanghai)
SET odps.sql.timezone=Asia/Shanghai;
-- Create the table (same as Example 2 above)
CREATE TABLE IF NOT EXISTS sale_detail2(
shop_name STRING,
total_price DOUBLE,
sale_time TIMESTAMP)
AUTO PARTITIONED BY (TRUNC_TIME(sale_time, 'day') AS sale_date);
-- Insert data
INSERT INTO sale_detail2 VALUES
('chongqin_shop', 101101, TIMESTAMP '2025-02-04 01:15:30'),
('shenzhen_shop', 202202, TIMESTAMP '2024-03-29 15:30:30'),
('hangzhou_shop', 303303, TIMESTAMP '2025-02-04 08:30:30'),
('shanghai_shop', 404404, TIMESTAMP '2025-02-28 01:50:30');
The table below shows how each sale_time value maps to a partition after TRUNC_TIME calculation:
sale_time (Asia/Shanghai, UTC+8) |
Partition sale_date (UTC) |
|---|---|
| 2025-02-04 01:15:30 | 2025-02-03 |
| 2024-03-29 15:30:30 | 2024-03-29 |
| 2025-02-04 08:30:30 | 2025-02-04 |
| 2025-02-28 01:50:30 | 2025-02-27 |
For DATETIME and TIMESTAMP columns,TRUNC_TIMEconverts local time to UTC before truncating. Rows written near midnight may land in a different partition than the local date suggests. For example,2025-02-04 01:15:30in UTC+8 is2025-02-03 17:15:30in UTC, so it is assigned to the2025-02-03partition, not2025-02-04.
Query an auto-partitioned table
**Example 1: SELECT * does not include the partition column by default**
-- Enable full table scan
SET odps.sql.allow.fullscan=true;
SELECT * FROM sale_detail2;
-- Result
+------------+-------------+---------------------+
| shop_name | total_price | sale_time |
+------------+-------------+---------------------+
| hangzhou_shop | 303303.0 | 2025-02-04 08:30:30 |
| shanghai_shop | 404404.0 | 2025-02-28 01:50:30 |
| shenzhen_shop | 202202.0 | 2024-03-29 15:30:30 |
| chongqin_shop | 101101.0 | 2025-02-04 01:15:30 |
+------------+-------------+---------------------+
Example 2: Include the partition column in the output
Reference the partition column by name to include it in results:
SELECT *, sale_date FROM sale_detail2;
-- Result
+------------+-------------+---------------------+------------+
| shop_name | total_price | sale_time | sale_date |
+------------+-------------+---------------------+------------+
| shanghai_shop | 404404.0 | 2025-02-28 01:50:30 | 2025-02-27 |
| hangzhou_shop | 303303.0 | 2025-02-04 08:30:30 | 2025-02-04 |
| shenzhen_shop | 202202.0 | 2024-03-29 15:30:30 | 2024-03-29 |
| chongqin_shop | 101101.0 | 2025-02-04 01:15:30 | 2025-02-03 |
+------------+-------------+---------------------+------------+
Partition pruning
Partition pruning reduces query cost by scanning only the partitions that match the filter condition. To verify whether partition pruning is working, check the SQL execution plan in Logview or use the EXPLAIN command. For details, see Evaluate the effectiveness of partition pruning.
Partition pruning is supported in three scenarios for auto-partitioned tables.
Filter on the generated partition column
Filtering directly on the partition column (sale_date) triggers partition pruning:
SELECT * FROM sale_detail2 WHERE sale_date > '2025-02-03';
-- Result: only partitions where sale_date > '2025-02-03' are scanned
+------------+-------------+---------------------+
| shop_name | total_price | sale_time |
+------------+-------------+---------------------+
| shanghai_shop | 404404.0 | 2025-02-28 01:50:30 |
| hangzhou_shop | 303303.0 | 2025-02-04 08:30:30 |
+------------+-------------+---------------------+
Filter on the source time column (without functions)
Filtering directly on the source time column (sale_time), without wrapping it in a function, also triggers partition pruning. The system maps the filter range to the corresponding partition boundaries:
SELECT * FROM sale_detail2 WHERE sale_time > '2025-02-04 08:00:00';
-- Result: only partitions containing matching sale_time values are scanned
+------------+-------------+---------------------+
| shop_name | total_price | sale_time |
+------------+-------------+---------------------+
| shanghai_shop | 404404.0 | 2025-02-28 01:50:30 |
| hangzhou_shop | 303303.0 | 2025-02-04 08:30:30 |
+------------+-------------+---------------------+
Filter using a function on the source time column
When you apply a function to the source time column in the filter condition, partition pruning works only if the function's truncation granularity matches the granularity used when the table was created. This is required because the system can map a filter condition to partition boundaries only when both express time at the same resolution.
| Function | Condition for partition pruning |
|---|---|
| TRUNC_TIME | Truncation granularity matches the table creation statement |
| DATETRUNC | Truncation granularity matches the table creation statement |
| CAST AS DATE | Table was created with day granularity |
| TO_DATE | Table was created with day granularity; no time zone parameter |
Example 1: Filter using `TRUNC_TIME` or `DATETRUNC` (without a time zone parameter)
Both queries trigger partition pruning because the truncation granularity (day / dd) matches the day granularity used to create sale_detail2, and neither function is called with a time zone parameter:
SELECT * FROM sale_detail2 WHERE TRUNC_TIME(sale_time, 'day') > '2025-02-04';
SELECT * FROM sale_detail2 WHERE DATETRUNC(sale_time, 'dd') > '2025-02-04 00:00:00';
-- Result
+------------+-------------+---------------------+
| shop_name | total_price | sale_time |
+------------+-------------+---------------------+
| shanghai_shop | 404404.0 | 2025-02-28 01:50:30 |
+------------+-------------+---------------------+
Example 2: Filter using `CAST AS DATE` or `TO_DATE` (without a time zone parameter)
Both queries trigger partition pruning because sale_detail2 was created with day granularity:
SELECT * FROM sale_detail2 WHERE CAST(sale_time AS DATE) = '2025-02-04';
SELECT * FROM sale_detail2 WHERE TO_DATE(sale_time) = '2025-02-04';
-- Result
+------------+-------------+---------------------+
| shop_name | total_price | sale_time |
+------------+-------------+---------------------+
| hangzhou_shop | 303303.0 | 2025-02-04 08:30:30 |
+------------+-------------+---------------------+