全部产品
Search
文档中心

云原生大数据计算服务 MaxCompute:OSS外部表相关分区操作

更新时间:Apr 01, 2026

本文介绍OSS外部表相关的分区操作,包括引入分区、添加分区、写入分区、删除分区以及Keyless Partition(分区表写出路径不包含分区key)的相关操作。

场景介绍

  • 创建的OSS外部表为分区表时,需要额外执行引入分区数据的操作。

    • 如需自动解析OSS目录结构,识别分区并为OSS外部表添加分区信息,请参见引入分区(MSCK)

    • 如需通过手动执行命令为OSS外部表添加分区信息,请参见添加分区

  • 如需向OSS外部表分区中写入数据,请参见写入分区

  • 如需删除OSS外部表的某个或多个分区,请参见删除分区

  • 如需通过OSS外部表向OSS写出的分区路径不包含分区key,请参见Keyless Partition

  • 如需获取OSS外部表最大分区的数据,请参见MAX_PT函数使用

引入分区(MSCK)

场景说明

创建的OSS外部表为分区表时,需要额外执行引入分区数据的操作。支持自动解析OSS目录结构,识别分区以及为OSS外部表添加分区信息。

  • MSCK方式适用于一次性补全全部缺失的历史分区的场景。MaxCompute会根据创建OSS外部表时指定的分区目录,自动补全OSS外部表的分区,而不用逐个按照分区列名和名称增加。

  • 该方式不适用于补充增量数据,尤其是在OSS目录中包含大量分区(如超过1000个)的情况下。当新增分区数量远少于已有分区时,频繁执行 MSCK 命令会导致 OSS 目录被大量重复扫描,并触发元数据更新,从而降低命令执行效率。对于需要更新增量分区的场景,建议采用添加分区的方式。

语法格式

MSCK REPAIR TABLE <mc_oss_extable_name>;

MSCK REPAIR TABLE <mc_oss_extable_name> ADD PARTITIONS [WITH PROPERTIES (key:VALUE, key:VALUE ...)];

使用示例

以CSV分区外部表为例,其他OSS外部表格式使用MSCK命令的方式相同。

  1. 准备分区数据

    1. 登录对象存储OSS控制台

    2. 在Bucket下创建Demo2目录,按分区列direction在该目录下创建子目录(direction=Ndirection=NEdirection=Sdirection=SWdirection=W),并上传对应的数据文件(vehicle1.csvvehicle2.csvvehicle3.csvvehicle4.csvvehicle5.csv)到各子目录中。操作详情参考附录:准备示例数据

  2. 创建OSS分区外部表

    CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external2
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitude DOUBLE,
      locationLongitude DOUBLE,
      recordTime STRING
    )
    PARTITIONED BY (
      direction STRING
    )
    STORED BY 'com.aliyun.odps.CsvStorageHandler'
    WITH SERDEPROPERTIES (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    )
    LOCATION 'oss://oss-cn-<region>-internal.aliyuncs.com/<bucket>/Demo2/';
  3. 引入分区

    MSCK REPAIR TABLE mc_oss_csv_external2 ADD PARTITIONS;
  4. 查询OSS外部表

    SELECT * FROM mc_oss_csv_external2 WHERE direction='NE';
    
    -- 返回结果如下:
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+
    | vehicleid | recordid | patientid | calls | locationlatitude | locationlongitude | recordtime | direction |
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+
    | 1         | 2        | 13        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE        |
    | 1         | 3        | 48        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE        |
    | 1         | 9        | 4         | 1     | 46.81006         | -92.08174         | 9/15/2014 0:00 | NE        |
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+

添加分区

场景说明

创建的OSS外部表为分区表时,需要额外执行引入分区数据的操作。当需要通过手动执行命令为OSS外部表添加分区信息时,可使用ALTER TABLE ADD PARTITION命令。

该方式适用于历史分区已经创建完成,需要频繁地周期性追加分区的场景。在执行数据写入任务之前创建好分区,即使OSS上有新数据写入,也不需要刷新对应分区,外部表即可读取OSS目录上的最新数据。

语法格式

ALTER TABLE <mc_oss_extable_name> 
  ADD PARTITION (<col_name>=<col_value>)[
  PARTITION (<col_name>=<col_value>)...][location URL];
  • col_namecol_value的值需要与分区数据文件所在目录名称对齐。一个ADD PARTITION对应一个子目录,多个OSS子目录需要使用多个ADD PARTITION

  • 例如,分区数据文件所在的OSS目录结构如下,col_name对应directioncol_value对应NNESSWW

    Demo2/
    ├── direction=N/
    ├── direction=NE/
    ├── direction=S/
    ├── direction=SW/
    └── direction=W/

使用示例

以CSV分区外部表为例,其他OSS格式外部表添加分区的方式相同。

  1. 准备分区数据

    1. 登录对象存储OSS控制台

    2. 在Bucket下创建Demo2目录,按分区列direction在该目录下创建子目录(direction=Ndirection=NEdirection=Sdirection=SWdirection=W),并上传对应的数据文件(vehicle1.csvvehicle2.csvvehicle3.csvvehicle4.csvvehicle5.csv)到各子目录中。操作详情参考附录:准备示例数据

  2. 创建OSS分区外部表

    CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external3
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitude DOUBLE,
      locationLongitude DOUBLE,
      recordTime STRING
    )
    PARTITIONED BY (
      direction STRING
    )
    STORED BY 'com.aliyun.odps.CsvStorageHandler'
    WITH SERDEPROPERTIES (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    )
    LOCATION 'oss://oss-cn-<region>-internal.aliyuncs.com/<bucket>/Demo2/';
  3. 添加分区

    ALTER TABLE mc_oss_csv_external3 ADD 
      PARTITION (direction='N')
      PARTITION (direction='NE')
      PARTITION (direction='S')
      PARTITION (direction='SW')
      PARTITION (direction='W');
  4. 查询OSS外部表

    SELECT * FROM mc_oss_csv_external3 WHERE direction='NE';
    
    -- 返回结果如下:
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+
    | vehicleid | recordid | patientid | calls | locationlatitude | locationlongitude | recordtime | direction |
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+
    | 1         | 2        | 13        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE        |
    | 1         | 3        | 48        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE        |
    | 1         | 9        | 4         | 1     | 46.81006         | -92.08174         | 9/15/2014 0:00 | NE        |
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+

写入分区

静态分区写入

场景说明

当需要以静态分区的方式向OSS外部表写入数据时,可使用以下操作。更多操作详情参见插入或覆写数据(INSERT INTO | INSERT OVERWRITE)

语法格式

INSERT {INTO|OVERWRITE} TABLE <mc_oss_extable_name> 
  PARTITION (<pt_spec>) [(<col_name> [,<col_name> ...)]]
  <select_statement> FROM <from_statement>;

使用示例

以CSV分区外部表为例,其他OSS格式外部表写入数据的方式相同。

  1. 创建OSS分区外部表

    CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external5
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitude DOUBLE,
      locationLongitude DOUBLE,
      recordTime STRING
    )
    PARTITIONED BY (
      direction STRING
    )
    STORED BY 'com.aliyun.odps.CsvStorageHandler'
    WITH SERDEPROPERTIES (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    )
    LOCATION 'oss://oss-cn-<region>-internal.aliyuncs.com/<bucket>/mc_oss_csv_external5';
  2. 以静态分区的方式写入数据

    INSERT INTO mc_oss_csv_external5 PARTITION (direction='SW')
      VALUES (1, 14, 76, 1, 46.81006, -92.08174, '9/14/2014 0:10');
    INSERT INTO mc_oss_csv_external5 PARTITION (direction='S')
      VALUES (1, 89, 76, 1, 46.81006, -92.08174, '9/14/2014 0:10');
  3. 查看写入结果

    SET odps.sql.allow.fullscan=true;
    SELECT * FROM mc_oss_csv_external5;
    
    -- 返回结果如下:
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+
    | vehicleid | recordid | patientid | calls | locationlatitude | locationlongitude | recordtime | direction |
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+
    | 1         | 89       | 76        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:10 | S         |
    | 1         | 14       | 76        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:10 | SW        |
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+

动态分区写入

场景说明

当需要以动态分区的方式向OSS外部表写入数据时,可使用以下操作。更多操作详情参见插入或覆写动态分区数据(DYNAMIC PARTITION)

语法格式

INSERT {INTO|OVERWRITE} TABLE <table_name> PARTITION (<ptcol_name>[, <ptcol_name> ...])
<select_statement> FROM <from_statement>;

使用示例

以CSV分区外部表为例,其他OSS格式外部表写入数据的方式相同。

  1. 准备测试表

    CREATE TABLE IF NOT EXISTS vehicle_test
    (
      vehicleid INT,
      recordid INT,
      patientid INT,
      calls INT,
      locationlatitude DOUBLE,
      locationlongitude DOUBLE,
      recordtime STRING,
      direction STRING
    );
    
    INSERT INTO vehicle_test VALUES (1, 1, 51, 1, 46.81006, -92.08174, '9/14/2014 0:00', 'S');
    INSERT INTO vehicle_test VALUES (1, 2, 13, 1, 46.81006, -92.08174, '9/14/2014 0:00', 'NE');
    INSERT INTO vehicle_test VALUES (1, 3, 48, 1, 46.81006, -92.08174, '9/14/2014 0:00', 'NE');
    INSERT INTO vehicle_test VALUES (1, 4, 30, 1, 46.81006, -92.08174, '9/14/2014 0:00', 'W');
    INSERT INTO vehicle_test VALUES (1, 5, 47, 1, 46.81006, -92.08174, '9/14/2014 0:00', 'S');
  2. 创建OSS分区外部表

    CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external6
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitute DOUBLE,
      locationLongtitue DOUBLE,
      recordTime STRING
    )
    PARTITIONED BY (
      direction STRING
    )
    STORED BY 'com.aliyun.odps.CsvStorageHandler'
    WITH SERDEPROPERTIES (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    )
    LOCATION 'oss://oss-cn-<region>-internal.aliyuncs.com/<bucket>/mc_oss_csv_external6';
  3. 以动态分区的方式写入数据

    INSERT INTO mc_oss_csv_external6 PARTITION(direction) SELECT * FROM vehicle_test;
  4. 查看写入结果

    SET odps.sql.allow.fullscan=true;
    SELECT * FROM mc_oss_csv_external6;
    
    -- 返回结果如下:
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+
    | vehicleid | recordid | patientid | calls | locationlatitude | locationlongitude | recordtime | direction |
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+
    | 1         | 4        | 30        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:00 | W         |
    | 1         | 2        | 13        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE        |
    | 1         | 3        | 48        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:00 | NE        |
    | 1         | 1        | 51        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:00 | S         |
    | 1         | 5        | 47        | 1     | 46.81006         | -92.08174         | 9/14/2014 0:00 | S         |
    +-----------+----------+-----------+-------+------------------+-------------------+------------+-----------+

删除分区

场景说明

创建的OSS外部表为分区表时,删除分区表的某个或多个分区。更多操作请参考分区操作

语法格式

ALTER TABLE <mc_oss_extable_name> DROP [IF EXISTS] PARTITION <pt_spec>[, PARTITION <pt_spec>...];

使用示例

  1. 基于添加分区的示例表mc_oss_csv_external3,查看该表的分区列表。

    SHOW PARTITIONS mc_oss_csv_external3;
    
    -- 返回结果如下:
    direction=N
    direction=NE
    direction=S
    direction=SW
    direction=W
    
    OK
  2. 删除direction=Sdirection=SW分区

    ALTER TABLE mc_oss_csv_external3 DROP IF EXISTS
      PARTITION (direction = 'S'), PARTITION (direction = 'SW');
  3. 再次查看分区列表,确认direction=Sdirection=SW分区已被删除

    SHOW PARTITIONS mc_oss_csv_external3;
    
    -- 返回结果如下:
    direction=N
    direction=NE
    direction=W
    
    OK

Keyless Partition

场景说明

当前场景下,通过写入OSS分区外部表生成的OSS分区目录包含分区key值(例如dt=20250724)。如需通过OSS外部表向OSS写出的分区路径不包含分区key,可使用Keyless Partition功能。

使用限制

  • 若使用固定value值的语法以动态分区形式写入外部表时则Keyless Partition参数无效,会生成<pt_col_name>=<pt_col_value>格式的OSS目录,且无法读出该目录下的数据。例如,INSERT OVERWRITE ext_tb PARTITION(dt) VALUES(1, 'xxx','20250724'), (2, 'xxx','20250724')

  • 不支持Paimon外部表、Hudi外部表、Delta Lake外部表。

语法格式

在创建外部表时添加TBLPROPERTIES参数,以CSV外部表为例如下。

CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name> 
(
  <col_name> <data_type>,
  ...
)
[COMMENT <table_comment>]
[PARTITIONED BY (<col_name> <data_type>, ...)] 
STORED BY 'com.aliyun.odps.CsvStorageHandler'  
[WITH serdeproperties (
  ['<property_name>'='<property_value>',...]
)] 
LOCATION '<oss_location>'
TBLPROPERTIES('odps.external.output.partition.keys.omitted' = 'true'); -- 该参数为true后,写出OSS的分区目录不包含分区key。

使用示例

以CSV分区外部表为例,其他格式使用方式相同。

  1. 创建CSV分区外部表

    CREATE EXTERNAL TABLE ext_csv_test03
    (
      id INT,
      name STRING
    )
    PARTITIONED BY (dt STRING)
    STORED BY 'com.aliyun.odps.CsvStorageHandler'
    LOCATION 'oss://oss-cn-<region>-internal.aliyuncs.com/<bucket>/keyless_partition/ext_csv_test03/'
    TBLPROPERTIES('odps.external.output.partition.keys.omitted' = 'true');
  2. 以静态分区的形式,向外部表写入常量数据

    INSERT INTO ext_csv_test03 PARTITION (dt='20250724')
      VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
    
    SELECT * FROM ext_csv_test03;
    -- 返回结果如下:
    +------+------+----------+
    | id   | name | dt       |
    +------+------+----------+
    | 1    | aaa  | 20250724 |
    | 2    | bbb  | 20250724 |
    | 3    | ccc  | 20250724 |
    +------+------+----------+

    OSS生成的目录如下,可以看到生成的20250724目录不包含分区keydt=

    ext_csv_test03/
    └── 20250724/
  3. 部分静态分区和部分动态分区的形式,向外部表写入数据

    形式上是动态分区写入,但由于values中的分区对应数据只有一个值'xxx',所以在MaxCompute的逻辑里是部分静态分区写入,部分动态分区写入。

    INSERT OVERWRITE ext_csv_test03 PARTITION(dt)
      VALUES (1, 'xxx','20250724'), (2, 'xxx','20250724');
    
    SELECT * FROM ext_csv_test03;
    
    -- 返回结果如下:
    -- 因为生成的OSS分区目录不符合要求,所以无法查出新插入的数据。只能查出步骤2静态写入的数据。
    +------+------+----------+
    | id   | name | dt       |
    +------+------+----------+
    | 1    | aaa  | 20250724 |
    | 2    | bbb  | 20250724 |
    | 3    | ccc  | 20250724 |
    +------+------+----------+

    OSS生成的目录如下,可以看到生成的dt=20250724目录包含分区keydt,所以此场景的写法不符合要求。

    ext_csv_test03/
    ├── 20250724/
    └── dt=20250724/
  4. 以动态分区的形式,向外部表写入常量数据

    INSERT OVERWRITE ext_csv_test03 PARTITION(dt)
      VALUES (1, 'xxx','20250725'), (2, 'yyy','20250726');
    
    SELECT * FROM ext_csv_test03;
    
    -- 返回结果如下:
    +------+------+----------+
    | id   | name | dt       |
    +------+------+----------+
    | 2    | yyy  | 20250726 |
    | 1    | xxx  | 20250725 |
    | 1    | aaa  | 20250724 |
    | 2    | bbb  | 20250724 |
    | 3    | ccc  | 20250724 |
    +------+------+----------+

    OSS生成的目录如下,可以看到生成的2025072520250726目录不包含分区keydt=

    ext_csv_test03/
    ├── 20250724/
    ├── 20250725/
    └── 20250726/
  5. 以动态分区的形式,向外部表写入SELECT子句的数据

    1. 准备测试表

      CREATE TABLE table03 (id INT, name STRING, dt STRING);
      INSERT INTO table03
        VALUES (6, 'fff', '20250725'), (7, 'ggg', '20250725'), (8, 'hhh', '20250723');
    2. 将测试表数据以SELECT子句的形式写入外部表

      INSERT OVERWRITE ext_csv_test03 PARTITION(dt) SELECT * FROM table03;
      
      SELECT * FROM ext_csv_test03;
      -- 返回结果如下:
      +------+------+----------+
      | id   | name | dt       |
      +------+------+----------+
      | 2    | yyy  | 20250726 |
      | 8    | hhh  | 20250723 |
      | 6    | fff  | 20250725 |
      | 7    | ggg  | 20250725 |
      | 1    | aaa  | 20250724 |
      | 2    | bbb  | 20250724 |
      | 3    | ccc  | 20250724 |
      +------+------+----------+

      OSS生成的目录如下,可以看到生成的2025072320250725目录不包含分区keydt=

      ext_csv_test03/
      ├── 20250723/
      ├── 20250724/
      ├── 20250725/
      └── 20250726/

MAX_PT函数使用

场景说明

当需要查询OSS外部表有数据的最大分区的数据时,可使用MAX_PT函数。更多操作请参考MAX_PT

注意事项

  • 当OSS外部表有多级分区时,MAX_PT只返回第一层有数据的分区中最大的分区值,且这个分区可以通过SHOW PARTITIONS列出。

  • 若在OSS目录下找不到任何有文件存在的分区,执行MAX_PT函数时会报错。

  • 对一个非分区表执行MAX_PT函数会报错。

语法格式

SELECT * FROM <mc_oss_extable_name>
WHERE <pt_col_name> = MAX_PT("<mc_oss_extable_name>");

-- 或者如下写法。
SELECT * FROM <mc_oss_extable_name>
WHERE <pt_col_name> = (SELECT MAX(<pt_col_name>) FROM <mc_oss_extable_name>);

使用示例

以CSV分区外部表为例,其他OSS格式外部表写入数据的方式相同。

  1. 创建OSS分区外部表并写入数据

    CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_csv_external9
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitude DOUBLE,
      locationLongitude DOUBLE,
      recordTime STRING,
      direction STRING
    )
    PARTITIONED BY (
      y STRING, m STRING
    )
    STORED BY 'com.aliyun.odps.CsvStorageHandler'
    WITH SERDEPROPERTIES (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    )
    LOCATION 'oss://oss-cn-<region>-internal.aliyuncs.com/<bucket>/mc_oss_csv_external9';
    
    INSERT INTO mc_oss_csv_external9 PARTITION(y='2023', m='03') VALUES (1, 89, 76, 1, 46.81606, -92.08174, '9/14/2014 0:10', 'SW');
    INSERT INTO mc_oss_csv_external9 PARTITION(y='2023', m='02') VALUES (1, 14, 76, 1, 47.90836, -92.08174, '9/14/2014 0:10', 'W');
    INSERT INTO mc_oss_csv_external9 PARTITION(y='2022', m='03') VALUES (1, 56, 76, 1, 48.81748, -92.08174, '9/14/2014 0:10', 'S');
    INSERT INTO mc_oss_csv_external9 PARTITION(y='2022', m='02') VALUES (1, 78, 76, 1, 49.81678, -92.08174, '9/14/2014 0:10', 'SE');
  2. OSS分区目录

    mc_oss_csv_external9/
    ├── y=2022/
          ├── m=02/
               └── d.csv
          └── m=03/
               └── c.csv
    └── y=2023/
          ├── m=02/
               └── b.csv
          └── m=03/
               └── a.csv
  3. 多级分区的OSS外部表,针对不同的目录下为空的场景,MAX_PT返回值是不同的,具体如下。

    1. 当OSS分区目录均不为空时,MAX_PT函数返回一级分区2023

      -- 查询外表的最大分区。
      SELECT MAX_PT("mc_oss_csv_external9");
      
      -- 返回结果:
      +-----+
      | _c0 |
      +-----+
      | 2023 |
      +-----+
    2. 当OSS分区目录的最大一级目录部分为空时,MAX_PT函数返回一级分区2023

      mc_oss_csv_external9/
      ├── y=2022/
            ├── m=02/
                 └── d.csv
            └── m=03/
                 └── c.csv
      └── y=2023/
            ├── m=02/
                 └── b.csv
            └── m=03/  -- 为空
      -- 查询外表的最大分区。
      SELECT MAX_PT("mc_oss_csv_external9");
      
      -- 返回结果:
      +-----+
      | _c0 |
      +-----+
      | 2023 |
      +-----+
    3. 当OSS分区目录的最大一级目录完全为空时,MAX_PT函数返回一级分区2022

      mc_oss_csv_external9/
      ├── y=2022/
            ├── m=02/
                 └── d.csv
            └── m=03/
                 └── c.csv
      └── y=2023/
            ├── m=02/  -- 为空
            └── m=03/  -- 为空
      -- 查询外表的最大分区。
      SELECT MAX_PT("mc_oss_csv_external9");
      
      -- 返回结果:
      +-----+
      | _c0 |
      +-----+
      | 2022 |
      +-----+
    4. 当分区目录的所有目录完全为空时,MAX_PT函数报错。

      SELECT MAX_PT("mc_oss_csv_external9");
      
      -- 返回报错:
      FAILED: ODPS-0130071:[1,8] Semantic analysis exception - 
        encounter runtime exception while evaluating function MAX_PT, 
        detailed message: table "project.default.mc_oss_csv_external9" 
        has no partitions or none of the partitions have any data