全部產品
Search
文件中心

MaxCompute:Parquet外部表格

更新時間:Aug 14, 2025

本文為您介紹Parquet格式的OSS外部表格的建立、讀取及寫入方法。

前提條件

  • 已具備訪問OSS的許可權。阿里雲帳號(主帳號)、RAM使用者或RAMRole身份可以訪問OSS外部表格,授權資訊請參見OSS的STS模式授權

  • (可選)已準備好OSS儲存空間(Bucket)、OSS目錄及OSS資料檔案。具體操作請參見建立儲存空間管理目錄簡單上傳

    MaxCompute已支援在OSS側自動建立目錄,對於攜帶外部表格及UDF的SQL語句,您可以通過一條SQL語句執行讀寫外部表格及UDF的操作。原手動建立目錄方式仍然支援。
  • 已建立MaxCompute專案。具體操作請參見建立MaxCompute專案

    由於MaxCompute只在部分地區部署,跨地區的資料連通性可能存在問題,因此建議Bucket與MaxCompute專案所在地區保持一致。
  • 已具備在MaxCompute專案中建立表(CreateTable)的許可權。表操作的許可權資訊請參見MaxCompute許可權

使用限制

  • OSS外部表格不支援cluster屬性。

  • 單個檔案大小不能超過3 GB,如果檔案過大,建議拆分。

注意事項

當Parquet檔案中的Schema與外表Schema不一致時:

  • 列數不一致:如果Parquet檔案中的列數小於外表DDL的列數,則讀取Parquet資料時,系統會將缺少的列值補充為NULL。反之(大於時),會丟棄超出的列資料。

  • 列類型不一致:如果Parquet檔案中的列類型與外表DDL中對應的列類型不一致,則讀取Parquet資料時會報錯。例如:使用STRING(或INT)類型接收Parquet檔案中INT(或STRING)類型的資料,報錯ODPS-0123131:User defined function exception - Traceback:xxx

資料類型支援

說明

下表中已開通表示支援,未開通表示不支援。

  • MaxCompute資料類型請參見1.0資料類型版本2.0資料類型版本

  • JNI模式:set odps.ext.parquet.native=false,表示讀外部表格解析Parquet資料檔案時,使用原有基於Java的開源社區實現,支援讀和寫。

  • Native模式:set odps.ext.parquet.native=true,表示讀外部表格解析Parquet資料檔案時,使用新的基於C++的Native實現,僅支援讀。

    資料類型

    是否支援JNI模式(讀寫)

    是否支援Native模式(唯讀)

    TINYINT

    已開通

    已開通

    SMALLINT

    已開通

    已開通

    INT

    已開通

    已開通

    BIGINT

    已開通

    已開通

    BINARY

    已開通

    已開通

    FLOAT

    已開通

    已開通

    DOUBLE

    已開通

    已開通

    DECIMAL(precision,scale)

    已開通

    已開通

    VARCHAR(n)

    已開通

    已開通

    CHAR(n)

    已開通

    已開通

    STRING

    已開通

    已開通

    DATE

    已開通

    已開通

    DATETIME

    已開通

    已開通

    TIMESTAMP

    已開通

    已開通

    TIMESTAMP_NTZ

    已開通

    已開通

    BOOLEAN

    已開通

    已開通

    ARRAY

    已開通

    已開通

    MAP

    已開通

    已開通

    STRUCT

    已開通

    已開通

    JSON

    未開通

    未開通

壓縮格式支援

當您需要讀寫壓縮屬性的OSS檔案時,需要在建表語句中添加with serdeproperties屬性配置,詳情請參見with serdeproperties屬性參數

支援讀寫的資料檔案格式:以ZSTD、SNAPPY、GZIP方式壓縮的Parquet。

建立外部表格

文法結構

各格式的外部表格文法結構詳情,請參見OSS外部表格

  • 精簡文法結構

    CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name>
    (
      <col_name> <data_type>,
      ...
    )
    [COMMENT <table_comment>]
    [PARTITIONED BY (<col_name> <data_type>, ...)]
    STORED AS parquet 
    LOCATION '<oss_location>' 
    [tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];
  • 詳細文法結構

    CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name>
    (
      <col_name> <data_type>,
      ...
    )
    [COMMENT <table_comment>]
    [PARTITIONED BY (<col_name> <data_type>, ...)]
    ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
    WITH serdeproperties(
        'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole',
        'mcfed.parquet.compression'='ZSTD/SNAPPY/GZIP'
    )
    STORED AS parquet 
    LOCATION '<oss_location>' 
    ;

公用參數

公用參數說明請參見基礎文法參數說明

私人參數

with serdeproperties屬性參數

property_name

使用情境

說明

property_value

預設值

mcfed.parquet.compression

當需要將Parquet資料以壓縮方式寫入OSS時,請添加該屬性。

Parquet壓縮屬性。Parquet資料預設不壓縮。

  • ZSTD

  • SNAPPY

  • GZIP

mcfed.parquet.compression.codec.zstd.level

'mcfed.parquet.compression'='zstd'時,可以添加該屬性。不填此屬性時,以預設值3進行壓縮。

level值越大,壓縮比越高,實測取值高時,寫出資料的減少量非常有限,但時間和資源消耗快速增加,性價比明顯降低,因此對於巨量資料讀寫壓縮Parquet檔案的情境,低level(level3~level5)的zstd壓縮效果最好。例如:'mcfed.parquet.compression.codec.zstd.level'= '5'

取值範圍為1~22。

3

parquet.file.cache.size

在處理Parquet資料情境中,如果需要提升讀OSS資料檔案效能,請添加該屬性。

指定讀OSS資料檔案時,可快取的資料量,單位為KB。

1024

parquet.io.buffer.size

在處理Parquet資料情境中,如果需要提升讀OSS資料檔案效能,請添加該屬性。

指定OSS資料檔案大小超過1024 KB時,可快取的資料量,單位為KB。

4096

tblproperties屬性參數

property_name

使用情境

說明

property_value

預設值

io.compression.codecs

當OSS資料檔案為Raw-Snappy格式時,請添加該屬性。

內建的開來源資料解析器SNAPPY格式情境。

配置該參數值為True時,MaxCompute才可以正常讀取壓縮資料,否則MaxCompute無法成功讀取資料。

com.aliyun.odps.io.compress.SnappyRawCodec

寫入資料

MaxCompute寫入文法詳情,請參見寫入文法說明

查詢分析

情境樣本

本樣本將建立以ZSTD壓縮的Parquet格式外表,並進行讀取和寫入操作。

說明
  • 執行下述範例程式碼時,請將代碼中的<uid>替換為您的阿里雲帳號ID。

  • 下述樣本中使用的角色為aliyunodpsdefaultrole,如果您想使用其他角色,需要將aliyunodpsdefaultrole替換為目標角色名稱,並為目標角色授予訪問OSS的許可權。

  1. 準備ZSTD格式資料檔案。

    樣本資料oss-mc-testBucket中建立parquet_zstd_jni/dt=20230418目錄層級,並將存放在分區目錄dt=20230418下。

  2. 建立ZSTD壓縮格式的Parquet外表。

    CREATE EXTERNAL TABLE IF NOT EXISTS mc_oss_parquet_data_type_zstd (
        vehicleId INT,
        recordId INT,
        patientId INT,
        calls INT,
        locationLatitute DOUBLE,
        locationLongtitue DOUBLE,
        recordTime STRING,
        direction STRING
    )
    PARTITIONED BY (dt STRING )
    ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
    WITH serdeproperties(
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole',
      'mcfed.parquet.compression'='zstd'
    )
    STORED AS parquet
    LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/parquet_zstd_jni/';
  3. 引入分區資料。當建立的OSS外部表格為分區表時,需要額外執行引入分區資料的操作,更多操作請參見補全OSS外部表格分區資料文法

    -- 引入分區資料
    MSCK REPAIR TABLE mc_oss_parquet_data_type_zstd ADD PARTITIONS;
  4. 讀取Parquet外表資料。

    SELECT * FROM mc_oss_parquet_data_type_zstd WHERE dt='20230418' LIMIT 10;

    部分返回結果如下:

    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+
    | vehicleid  | recordid   | patientid  | calls      | locationlatitute | locationlongtitue | recordtime     | direction  | dt         |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+
    | 1          | 12         | 76         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:10 | SW         | 20230418   |
    | 1          | 1          | 51         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:00 | S          | 20230418   |
    | 1          | 2          | 13         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:01 | NE         | 20230418   |
    | 1          | 3          | 48         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:02 | NE         | 20230418   |
    | 1          | 4          | 30         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:03 | W          | 20230418   |
    | 1          | 5          | 47         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:04 | S          | 20230418   |
    | 1          | 6          | 9          | 1          | 46.81006         | -92.08174         | 9/14/2014 0:05 | S          | 20230418   |
    | 1          | 7          | 53         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:06 | N          | 20230418   |
    | 1          | 8          | 63         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:07 | SW         | 20230418   |
    | 1          | 9          | 4          | 1          | 46.81006         | -92.08174         | 9/14/2014 0:08 | NE         | 20230418   |
    | 1          | 10         | 31         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:09 | N          | 20230418   |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+
  5. 寫入資料至Parquet外表。

    INSERT INTO mc_oss_parquet_data_type_zstd PARTITION ( dt = '20230418') 
      VALUES  (1,16,76,1,46.81006,-92.08174,'9/14/2014 0:10','SW');
    
    -- 查詢新寫入的資料
    SELECT * FROM mc_oss_parquet_data_type_zstd WHERE ds = '20230606' AND recordId=16;

    返回結果如下:

    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+
    | vehicleid  | recordid   | patientid  | calls      | locationlatitute | locationlongtitue | recordtime     | direction  | dt         |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+
    | 1          | 16         | 76         | 1          | 46.81006         | -92.08174         | 9/14/2014 0:10 | SW         | 20230418   |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+

常見問題

Parquet檔案列類型與外表DDL類型不一致

  • 報錯資訊

    ODPS-0123131:User defined function exception - Traceback:
    java.lang.ClassCastException: org.apache.hadoop.io.LongWritable cannot be cast to org.apache.hadoop.io.IntWritable 
       at org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableIntObjectInspector.getPrimitiveJavaObject(WritableIntObjectInspector.java:46)
  • 錯誤描述

    Parquet檔案的LongWritable欄位類型與外表DDL的INT類型不一致。

  • 解決方案

    外表DDL中的INT類型需要改為BIGINT類型。