本文為您介紹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。
資料類型支援
下表中
表示支援,
表示不支援。
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資料預設不壓縮。 |
| 無 |
mcfed.parquet.compression.codec.zstd.level | 當 | level值越大,壓縮比越高,實測取值高時,寫出資料的減少量非常有限,但時間和資源消耗快速增加,性價比明顯降低,因此對於巨量資料讀寫壓縮Parquet檔案的情境,低level(level3~level5)的zstd壓縮效果最好。例如: | 取值範圍為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寫入文法詳情,請參見寫入文法說明。
查詢分析
SELECT文法詳情,請參見查詢文法說明。
最佳化查詢計劃詳情,請參見查詢最佳化。
若需要直讀LOCATION檔案,請參見特色功能:Schemaless Query。
情境樣本
本樣本將建立以ZSTD壓縮的Parquet格式外表,並進行讀取和寫入操作。
執行下述範例程式碼時,請將代碼中的
<uid>替換為您的阿里雲帳號ID。下述樣本中使用的角色為
aliyunodpsdefaultrole,如果您想使用其他角色,需要將aliyunodpsdefaultrole替換為目標角色名稱,並為目標角色授予訪問OSS的許可權。
準備ZSTD格式資料檔案。
在樣本資料的
oss-mc-testBucket中建立parquet_zstd_jni/dt=20230418目錄層級,並將存放在分區目錄dt=20230418下。建立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/';引入分區資料。當建立的OSS外部表格為分區表時,需要額外執行引入分區資料的操作,更多操作請參見補全OSS外部表格分區資料文法。
-- 引入分區資料 MSCK REPAIR TABLE mc_oss_parquet_data_type_zstd ADD PARTITIONS;讀取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 | +------------+------------+------------+------------+------------------+-------------------+----------------+------------+------------+寫入資料至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類型。