Parquet外部表

本文为您介绍Parquet格式的OSS外部表的创建、读取及写入方法。

前提条件

  • 已具备访问OSS的权限。阿里云账号(主账号)、RAM用户或RAMRole身份可以访问OSS外部表,授权信息请参见OSSSTS模式授权

  • (可选)已准备好OSS存储空间(Bucket)、OSS目录及OSS数据文件。具体操作请参见创建存储空间管理目录简单上传

    MaxCompute已支持在OSS侧自动创建目录,对于携带外部表及UDFSQL语句,您可以通过一条SQL语句执行读写外部表及UDF的操作。原手动创建目录方式仍然支持。
  • 已创建MaxCompute项目。具体操作请参见创建MaxCompute项目

    由于MaxCompute只在部分地域部署,跨地域的数据连通性可能存在问题,因此建议BucketMaxCompute项目所在地域保持一致。
  • 已具备在MaxCompute项目中创建表(CreateTable)的权限。表操作的权限信息请参见MaxCompute权限

使用限制

  • OSS外部表不支持cluster属性。

  • 单个文件大小不能超过3 GB,如果文件过大,建议拆分。

数据类型支持

说明

下表中已开通表示支持,未开通表示不支持。

  • 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目录层级,并将Parquet文件存放在分区目录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/';
    
    -- 引入分区数据
    MSCK REPAIR TABLE mc_oss_parquet_data_type_zstd ADD PARTITIONS;
  3. 读取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   |
    +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+
  4. 写入数据至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字段类型与外表DDLINT类型不一致。

  • 解决方案

    外表DDL中的INT类型需要改为BIGINT类型。