特色功能:Schemaless Query

MaxCompute支持免定义查询(Schemaless Query)OSSParquet外部表数据,解析后的数据集结果可以导出至OSS或写入内部表,同时也可以作为子查询嵌入SQL运算,从而便捷地操作湖上数据。

背景信息

使用Spark处理结构化数据的用户在进行临时数据探查时,并不需要依赖固定的数仓模型。如果输入和输出都需要定义表结构,并将OSS上的文件字段映射到外表字段,才能进行读写操作,那么后续维护分区的过程将显得相对繁琐。

若可以在使用Load指令读取Parquet外部表时,自动解析文件格式,并将数据读取为一个带有Schema的数据集(Dataset)。用户就可以直接在结果上选择部分列进行类似基于表的数据处理,生成的结果可通过Unload命令直接导出至OSS,或者通过CREATE TABLE AS导入到内部表中。也可以将该Dataset作为其他SQL的子查询,从而在SQL运算中灵活使用MaxCompute操作湖上的数据。

使用限制

Schemaless Query暂不支持把OSS Bucket中的子目录当作分区处理。

语法结构

SELECT *, <col_name>, <table_alias>.<col_name> 
FROM 
 LOCATION '<location_path>'  
 ('key'='value' [, 'key1'='value1', ...]) 
 [AS <table_alias>];

参数说明

参数

是否必填

说明

*

查询Parquet文件中的所有字段。

col_name

查询Parquet文件中已知列名的字段。

table_alias.col_name

查询Parquet文件中已知列名的字段,以表别名和字段名完整路径方式表达。

table_alias

自定义表别名。

location_path

Parquet文件的location,必须是一个OSS目录,结构为oss://oss_endpoint/bucket_name/path/。

path的下一级支持partition_name=partition_value格式的分区目录。

说明

Schemaless Query暂不支持把location中的子目录当作分区处理,因此不支持分区裁剪。

key&value

查询语句的参数和参数值。详情如下表。

key&value可选参数:

key

value

是否必填

说明

默认值

file_format

parquet

指定Location文件的格式仅支持Parquet,其他格式将报错并提示不支持。

parquet

rolearn

acs:ram::xxxxxx:role/aliyunodpsdefaultrole

指定访问Location所需Rolearn。您可以通过RAM控制台中的角色页面搜索AliyunODPSDefaultRole进行获取。

说明

SQL语句中,如果未指定Rolearn,系统将默认使用AliyunODPSDefaultRole角色的ARN信息。

acs:ram::1234****:role/aliyunodpsdefaultrole

file_pattern_blacklist

正则表达式。如:

".*_SUCCESS$,.*\\.hive_staging.*"

指定需要读取的文件的黑名单。若扫描的文件名字匹配黑名单,则不读取该文件。

file_pattern_whitelist

正则表达式。如:

".*_20250124_.*.parquet"

指定需要读取的文件的白名单。只有扫描的文件名字匹配白名单,才读取该文件。

.*

使用示例

示例1:通过设置黑白名单参数读取OSS数据

  1. 准备数据。

    登录OSS控制台,上传测试数据至OSS Bucket指定目录object-table-test/schema/。具体操作请参见OSS文件上传

    • 准备一个Parquet文件用来读取以及验证白名单参数:。

    • 准备一个CSV文件用来验证黑名单参数:

    oss1

  2. 读取Parquet文件。

    登录MaxCompute客户端(odpscmd),执行如下SQL命令。

    • 添加test_oss.csv为黑名单参数,读取OSSParquet文件。

      SELECT tinyint_name, int_name, binary_name, float_name,varchar_name 
      FROM location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/schema/'
      (
      'file_format'='parquet',
      'rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole',
      'file_pattern_blacklist'='.*test_oss.*'
      );
    • 添加20250610TableSink为白名单参数,读取OSSParquet文件。

      SELECT tinyint_name, int_name, binary_name, float_name, varchar_name 
      FROM location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/schema/'
      (
      'file_format'='parquet',
      'rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole',
      'file_pattern_whitelist'='.*20250610TableSink.*'
      );

    以上参数配置情形,均在读取20250610TableSink文件,返回结果如下:

    +--------------+------------+-------------+------------+--------------+
    | tinyint_name | int_name   | binary_name | float_name | varchar_name |
    +--------------+------------+-------------+------------+--------------+
    | 1            | 100        | abc         | 3.14       | N            |
    +--------------+------------+-------------+------------+--------------+

示例2:读取Spark写入的数据

  1. 基于Serverless Spark生成Parquet数据。更多操作请参见创建SQL任务

    说明
    1. 登录E-MapReduce控制台,创建EMR Serverless-Spark工作空间。

    2. EMR Serverless > Spark页面,单击进入新建的工作空间,在数据开发页面执行如下SQL。

      CREATE TABLE example_table_parquet04 (
          id STRING,
          name STRING,
          age STRING,
          salary DOUBLE,
          is_active BOOLEAN,
          created_at TIMESTAMP,
          details STRUCT<department:STRING, position:STRING>
      )
      USING PARQUET;
      
      INSERT INTO example_table_parquet04 VALUES
      ('1', 'Alice', '30', 5000.50, TRUE, TIMESTAMP '2024-01-01 10:00:00', STRUCT('HR', 'Manager')),
      ('2', 'Bob', '25', 6000.75, FALSE, TIMESTAMP '2024-02-01 11:00:00', STRUCT('Engineering', 'Developer')),
      ('3', 'Charlie','35', 7000.00, TRUE, TIMESTAMP '2024-03-01 12:00:00', STRUCT('Marketing', 'Analyst')),
      ('4', 'David', '40', 8000.25, FALSE, TIMESTAMP '2024-04-01 13:00:00', STRUCT('Sales', 'Representative')),
      ('5', 'Eve', '28', 5500.50, TRUE, TIMESTAMP '2024-05-01 14:00:00', STRUCT('Support', 'Technician'));
      
      SELECT * FROM example_table_parquet04;
  2. 登录OSS控制台,在目标路径下查看生成的数据文件。image

  3. 登录MaxCompute客户端,添加_SUCCESS为黑名单参数,读取OSSParquet文件。假设OSS指定目录为object-table-test/spark

    SELECT  *
    from location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/spark/example_table_parquet04/'
    (
    'file_format'='parquet',
    'rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole',
    'file_pattern_blacklist'='.*_SUCCESS.*'
    );

    返回结果如下:

    +----+---------+-----+------------+-----------+---------------------+----------------------------------------------+
    | id | name    | age | salary     | is_active | created_at          | details                                      |
    +----+---------+-----+------------+-----------+---------------------+----------------------------------------------+
    | 1  | Alice   | 30  | 5000.5     | true      | 2024-01-01 10:00:00 | {department:HR, position:Manager}            |
    | 2  | Bob     | 25  | 6000.75    | false     | 2024-02-01 11:00:00 | {department:Engineering, position:Developer} |
    | 3  | Charlie | 35  | 7000.0     | true      | 2024-03-01 12:00:00 | {department:Marketing, position:Analyst}     |
    | 4  | David   | 40  | 8000.25    | false     | 2024-04-01 13:00:00 | {department:Sales, position:Representative}  |
    | 5  | Eve     | 28  | 5500.5     | true      | 2024-05-01 14:00:00 | {department:Support, position:Technician}    |
    +----+---------+-----+------------+-----------+---------------------+----------------------------------------------+

示例3:子查询使用Schemaless Query

  1. 准备数据。

    登录OSS控制台,上传测试数据part-00001.snappy.parquetOSS Bucket指定目录object-table-test/schema/。具体操作请参见OSS文件上传

  2. 登录MaxCompute客户端,创建内部表,用于接收自动探查到的OSS数据。

    CREATE TABLE ow_test (
        id INT,
        name STRING,
        age INT
    );
  3. 通过Schemaless Query读取OSS数据,命令如下。

    SELECT * FROM 
    LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/schema/' 
    (
      'file_format'='parquet'
    );

    返回结果如下:

    +------------+------------+------------+
    | id         | name       | age        |
    +------------+------------+------------+
    | 3          | Charlie    | 35         |
    | 4          | David      | 40         |
    | 5          | Eve        | 28         |
    +------------+------------+------------+
  4. 将读取的OSS数据作为子查询传给外部SQL,并查询结果表ow_test。

    INSERT OVERWRITE TABLE ow_test
    SELECT id,name,age FROM 
    (
        SELECT * FROM 
        LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/schema/' 
        (
          'file_format'='parquet'
        )
    );
    
    SELECT * FROM ow_test;

    返回结果如下:

    +------------+------------+------------+
    | id         | name       | age        |
    +------------+------------+------------+
    | 3          | Charlie    | 35         |
    | 4          | David      | 40         |
    | 5          | Eve        | 28         |
    +------------+------------+------------+

示例4:将Schemaless Query结果转存为数仓内部表

  1. 准备数据。

    登录OSS控制台,上传测试数据part-00001.snappy.parquetOSS Bucket指定目录object-table-test/schema/。具体操作请参见OSS文件上传

  2. 登录MaxCompute客户端,通过Schemaless Query读取OSS数据。

    SELECT * FROM 
    LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/schema/' 
    (
      'file_format'='parquet'
    );

    返回结果如下:

    +------------+------------+------------+
    | id         | name       | age        |
    +------------+------------+------------+
    | 3          | Charlie    | 35         |
    | 4          | David      | 40         |
    | 5          | Eve        | 28         |
    +------------+------------+------------+
  3. 将自动探查到的OSS数据通过CREATE TABLE AS语句复制到内表中,并查询结果。

    CREATE TABLE ow_test_2 AS 
      SELECT * FROM 
      LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/schema/' 
      (
        'file_format'='parquet'
       );
    
    -- 查询结果表ow_test_2
    SELECT * FROM ow_test_2;

    返回结果如下:

    +------------+------------+------------+
    | id         | name       | age        |
    +------------+------------+------------+
    | 3          | Charlie    | 35         |
    | 4          | David      | 40         |
    | 5          | Eve        | 28         |
    +------------+------------+------------+

示例5:将Schemaless Query结果UNLOAD回数据湖

  1. 准备数据。

    登录OSS控制台,上传测试数据part-00001.snappy.parquetOSS Bucket指定目录object-table-test/schema/。具体操作请参见OSS文件上传

  2. 登录MaxCompute客户端,通过Schemaless Query读取OSS数据。

    SELECT * FROM 
    LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/schema/' 
    (
      'file_format'='parquet'
    );

    返回结果如下:

    +------------+------------+------------+
    | id         | name       | age        |
    +------------+------------+------------+
    | 3          | Charlie    | 35         |
    | 4          | David      | 40         |
    | 5          | Eve        | 28         |
    +------------+------------+------------+
  3. 将自动探查到的结果UNLOADOSS,更多UNLOAD操作,请参见UNLOAD

    UNLOAD FROM (
      SELECT * FROM 
      LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/schema/' 
      ('file_format'='parquet')
    ) 
    INTO 
    LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/unload/ow_test_3/'
    ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
    WITH SERDEPROPERTIES ('odps.external.data.enable.extension'='true')
    STORED AS PARQUET;

    查看OSS的目录下已生成文件:image