全部產品
Search
文件中心

MaxCompute:OSS外部表格

更新時間:Sep 18, 2025

MaxCompute支援您在專案中建立OSS(Object Storage Service)外部表格,與儲存服務OSS上的目錄建立映射關係,您可以通過OSS外部表格訪問OSS目錄下的資料檔案中的非結構化資料,或將MaxCompute專案中的資料寫入OSS目錄。本文為您介紹建立、讀取和寫入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外部表格只是記錄與OSS目錄的映射關係。當刪除OSS外部表格時,不會刪除映射的OSS目錄下的資料檔案。

  • OSS資料檔案類型為歸檔檔案時,需要先解凍檔案

  • 請使用OSS傳統網路網域名稱。對於公網的網路網域名稱,MaxCompute不保證網路連通性。

使用限制

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

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

操作入口

MaxCompute支援通過以下平台建立OSS外部表格、對外部表格執行讀取和寫入操作。

方式

平台

基於MaxCompute SQL的方式

可視化方式

建立OSS外部表格

OSS外部表格分為分區表和非分區表,具體類型需要根據資料檔案在OSS中的儲存直接選取。當資料檔案以分區路徑方式儲存時,需要建立分區表,否則建立非分區表。

注意事項

對於不同格式的資料檔案,建立OSS外部表格語句在個別參數設定上會不同,請根據建立OSS外部表格文法及參數說明建立符合業務需求的外部表格,否則讀取OSS資料或將資料寫入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 BY '<StorageHandler>'  
    WITH serdeproperties (
     ['<property_name>'='<property_value>',...]
    ) 
    location '<oss_location>';

    支援讀取或寫入OSS的資料檔案格式:

    • CSV

    • TSV

    • 以GZIP、SNAPPY或LZO方式壓縮的CSV、TSV

  • 情境:通過內建開來源資料解析器建立外部表格

    文法格式

    資料檔案格式

    樣本

    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 '<serde_class>'
      [WITH serdeproperties (
        ['<property_name>'='<property_value>',...])
      ]
    ]
    stored AS <file_format> 
    location '<oss_location>' 
    [USING '<resource_name>']
    [tblproperties ('<tbproperty_name>'='<tbproperty_value>',...)];

    支援讀取或寫入OSS的資料檔案格式:

    • PARQUET

    • TEXTFILE

    • ORC

    • RCFILE

    • AVRO

    • JSON

    • SEQUENCEFILE

    • Hudi(僅支援讀取DLF產生的Hudi資料)

    • 以ZSTD、SNAPPY或GZIP方式壓縮的PARQUET

    • 以SNAPPY、ZLIB方式壓縮的ORC

    • 以GZIP、SNAPPY、LZO方式壓縮的TEXTFILE

  • 情境:通過自訂解析器建立外部表格

    文法格式

    資料檔案格式

    樣本

    CREATE EXTERNAL TABLE [IF NOT EXISTS] <mc_oss_extable_name> 
    (
    <col_name> <date_type>,
    ...
    )
    [comment <table_comment>]
    [partitioned BY (<col_name> <data_type>, ...)] 
    stored BY '<StorageHandler>' 
    WITH serdeproperties (
     ['<property_name>'='<property_value>',...]
    ) 
    location '<oss_location>' 
    USING '<jar_name>';

    支援讀取或寫入OSS的資料檔案格式:除上述格式外的資料檔案。

參數說明

以下為各類格式外表的公用參數說明,您可以在對應格式的文檔中查看並使用其專屬參數。

  • 基礎文法參數說明

    參數名稱

    是否必填

    說明

    mc_oss_extable_name

    待建立的OSS外部表格的名稱。

    表名大小寫不敏感,在查詢外部表格時,無需區分大小寫,且不支援強制轉換大小寫。

    col_name

    OSS外部表格的列名稱。

    在讀取OSS資料情境,建立的OSS外部表格結構必須與OSS資料檔案結構保持一致,否則無法成功讀取OSS資料。

    data_type

    OSS外部表格的列資料類型。

    在讀取OSS的資料情境,OSS外部表格各列資料類型必須與OSS資料檔案各列資料類型保持一致,否則無法成功讀取OSS資料。

    table_comment

    表注釋內容。注釋內容為長度不超過1024位元組的有效字串,否則報錯。

    partitioned by (col_name data_type, ...)

    當OSS中的資料檔案是以分區路徑方式儲存時,需要攜帶該參數,建立分區表。

    • col_name:分區列名稱。

    • data_type:分區列資料類型。

    '<(tb)property_name>'='<(tb)property_value>'

    OSS外部表格擴充屬性,參數詳解見各格式文檔專屬參數。

    oss_location

    資料檔案所在OSS路徑。預設讀取該路徑下的所有資料檔案。

    格式為oss://<oss_endpoint>/<Bucket名稱>/<OSS目錄名稱>/

    • oss_endpoint

      • OSS訪問網域名稱資訊。需要使用OSS提供的傳統網路網域名稱,即帶 -internal 的endpoint。

        例如oss://oss-cn-beijing-internal.aliyuncs.com/xxx

        更多OSS傳統網路網域名稱資訊,請參見OSS地區和訪問網域名稱

        建議資料檔案存放的OSS地區與MaxCompute專案所在地區保持一致。如果跨地區,資料連通性可能存在問題。
      • 不寫endpoint。系統會預設補充一個當前Project所在地區的endpoint。

        不推薦這種方式,如果檔案儲存體跨地區,可能存在資料連通性問題。
    • Bucket名稱:OSS儲存空間名稱。

      例如oss://oss-cn-beijing-internal.aliyuncs.com/your_bucket/path/

      更多查看儲存空間名稱資訊,請參見列舉儲存空間

    • 目錄名稱:OSS目錄名稱。目錄後不需要指定檔案名稱。

      例如oss://oss-cn-beijing-internal.aliyuncs.com/oss-mc-test/Demo1/

      錯誤樣本:

       -- 不支援HTTP串連。
      http://oss-cn-shanghai-internal.aliyuncs.com/oss-mc-test/Demo1/
      -- 不支援HTTPS串連。               
      https://oss-cn-shanghai-internal.aliyuncs.com/oss-mc-test/Demo1/
      -- 串連地址錯誤。            
      oss://oss-cn-shanghai-internal.aliyuncs.com/Demo1
      -- 不需要指定檔案名稱。                            
      oss://oss-cn-shanghai-internal.aliyuncs.com/oss-mc-test/Demo1/vehicle.csv
    • 許可權規範(RamRole

      • 顯示指定(推薦):建立自訂角色並綁定權限原則,使用該自訂角色的ARN資訊,建立詳情請參見STS模式授權

      • 使用Default(不推薦):使用aliyunodpsdefaultrole角色的ARN資訊。

  • WITH serdeproperties屬性

    property_name

    使用情境

    property_value

    預設值

    odps.properties.rolearn

    使用STS模式授權時,請添加該屬性。

    指定RAM中Role(具有訪問OSS許可權)的ARN資訊。您可以通過RAM控制台中的角色詳情進行擷取。樣本如下acs:ram::xxxxxx:role/aliyunodpsdefaultrole

    • 當MaxCompute和OSS的Owner是同一個帳號時

      • 若建表語句中不寫odps.properties.rolearn,預設使用aliyunodpsdefaultrole角色的ARN資訊。

      • 若您想用自訂角色的ARN資訊,需要提前建立自訂角色,建立詳情請參見OSS的STS模式授權(方式二)

    • 當MaxCompute和OSS的Owner不是同一個帳號時,您需要填寫自訂角色的ARN資訊,建立詳情請參見OSS的STS模式授權(方式三)

補全OSS外部表格分區資料文法

建立的OSS外部表格為分區表時,需要額外執行引入分區資料的操作,具體如下。

  • 方式一(推薦):自動解析OSS目錄結構,識別分區,為OSS外部表格添加分區資訊。

    該方式適用於一次性補全全部缺失的歷史分區的情境。MaxCompute會根據您建立OSS外部表格時指定的分區目錄,自動補全OSS外部表格的分區,而不用逐個按照分區列名和名稱增加。

    MSCK REPAIR TABLE <mc_oss_extable_name> ADD PARTITIONS [ WITH properties (key:VALUE, key: VALUE ...)];
    該方式不適用於處理增量資料的補充,尤其是在OSS目錄中包含大量分區(如超過1000個)的情況下。當新增的分區遠少於已有分區時,頻繁使用msck命令會導致對OSS目錄大量的重複掃描和中繼資料更新情況,從而降低命令執行的效率。對於需要更新增量分區的情境,建議採用方式二。
  • 方式二:手動執行命令為OSS外部表格添加分區資訊。

    該方式適用於歷史分區已經建立完成,需要頻繁地周期性追加分區的情境。在執行資料寫入任務之前建立好分區,即使OSS上有新資料寫入,也不需要重新整理對應分區,外部表格即可讀取OSS目錄上的最新資料。

    ALTER TABLE <mc_oss_extable_name> 
      ADD PARTITION (<col_name>=<col_value>)[
      ADD PARTITION (<col_name>=<col_value>)...][location URL];

    col_namecol_value的值需要與分區資料檔案所在目錄名稱對齊。

    假設,分區資料檔案所在的OSS目錄結構如下圖,col_name對應directioncol_value對應N、NE、S、SW、W。一個add partition對應一個子目錄,多個OSS子目錄需要使用多個add partition

    分區路徑

讀取OSS資料

注意事項

  • 建立好OSS外部表格後,才可以通過外部表格讀取OSS資料。MaxCompute支援的OSS資料檔案類型及建立OSS外部表格文法,請參見文法說明

  • SQL語句中涉及到複雜資料類型時,需要在SQL語句前添加set odps.sql.type.system.odps2=true;命令,然後一起提交執行。資料類型相關資訊請參見資料類型版本說明

  • 對於映射開來源資料的OSS外部表格,需要在Session層級設定set odps.sql.hive.compatible=true;後再讀取OSS資料,否則會報錯。

  • OSS對外提供的頻寬資源有限,若短時間內資料讀寫流量超過執行個體頻寬上限,會直接影響OSS外表的資料讀寫速度。關於OSS頻寬詳情,請參見使用限制及效能指標

文法說明

<select_statement> FROM <from_statement>;
  • select_statement:SELECT子句,從源表中查詢需要插入目標表的資料。

  • from_statement:FROM子句,資料來源,如外表名稱。

非分區資料

建立OSS外部表格(非分區表)後,讀取OSS資料方式如下:

  • 方式一(推薦):將OSS的開源格式資料匯入MaxCompute內部表,然後再讀取OSS資料。

    該方式適用於需要對資料進行反覆計算或對計算效能要求高的情境。通過在MaxCompute專案中建立與OSS外部表格Schema相同的內部表,將OSS資料匯入該內部表後執行複雜查詢,可充分利用MaxCompute針對內部儲存的最佳化機制,提升計算效能。命令樣本如下:

    CREATE TABLE <table_internal> LIKE <mc_oss_extable_name>;
    INSERT OVERWRITE TABLE <table_internal> SELECT * FROM <mc_oss_extable_name>;
  • 方式二:與MaxCompute內部表的操作一致,直接讀取OSS資料。

    該方式適用於對計算效能要求不高的情境。與讀取內部表不同的是,每次讀取資料都是直接從OSS讀取對應的資料。

分區資料

建立OSS外部表格後,MaxCompute會全量掃描OSS目錄下的所有資料,包括子目錄下的資料檔案。當資料量較大時,對全量目錄掃描會產生不必要的I/O消耗以及資料處理時間。解決該問題有如下兩種方式。

  • 方式一(推薦):在OSS上將資料以標準分區路徑自訂分區路徑方式儲存。

    建立OSS外部表格時,需要在建表語句中指定分區及oss_location資訊。推薦使用標準分區路徑儲存OSS資料。

  • 方式二:規劃多個資料存放路徑。

    建立多個OSS外部表格讀取各個路徑下的資料,即每個OSS外部表格指向OSS資料的一個子集。該方式操作繁瑣,資料管理效果不佳,不推薦使用。

標準分區路徑格式

oss://<oss_endpoint>/<Bucket名稱>/<目錄名稱>/<partitionKey1=value1>/<partitionKey2=value2>/...

樣本:某公司會將每天產生的Log檔案以CSV格式存放在OSS上,並通過MaxCompute以天為周期處理資料。則儲存OSS資料的標準分區路徑應設定如下。

oss://oss-odps-test/log_data/year=2016/month=06/day=01/logfile
oss://oss-odps-test/log_data/year=2016/month=06/day=02/logfile
oss://oss-odps-test/log_data/year=2016/month=07/day=10/logfile
oss://oss-odps-test/log_data/year=2016/month=08/day=08/logfile
...

自訂分區路徑格式

自訂分區路徑格式:只有分區列值,沒有分區列名。樣本如下:

oss://oss-odps-test/log_data_customized/2016/06/01/logfile
oss://oss-odps-test/log_data_customized/2016/06/02/logfile
oss://oss-odps-test/log_data_customized/2016/07/10/logfile
oss://oss-odps-test/log_data_customized/2016/08/08/logfile
...

OSS的資料已按照分區方式儲存,但其路徑並非標準分區路徑格式,MaxCompute支援將不同的子目錄綁定至不同的分區,從而訪問子目錄資料。

實現方案:建立OSS外部表格後,通過alter table ... add partition ... location ...命令指定子目錄,將不同的子目錄綁定到不同的分區,命令樣本如下。

ALTER TABLE log_table_external ADD PARTITION (year = '2016', month = '06', day = '01')
location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/bucket名稱/oss-odps-test/log_data_customized/2016/06/01/';
ALTER TABLE log_table_external ADD PARTITION (year = '2016', month = '06', day = '02')
location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/bucket名稱/oss-odps-test/log_data_customized/2016/06/02/';
ALTER TABLE log_table_external ADD PARTITION (year = '2016', month = '07', day = '10')
location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/bucket名稱/oss-odps-test/log_data_customized/2016/07/10/';
ALTER TABLE log_table_external ADD PARTITION (year = '2016', month = '08', day = '08')
location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/bucket名稱/oss-odps-test/log_data_customized/2016/08/08/';

查詢最佳化

  • 動態統計資訊收集

    由於資料存放區在外部資料湖且缺乏預先統計資訊,查詢最佳化工具採用保守策略,查詢效率低。動態統計資訊收集功能支援Optimizer在Query執行中臨時統計表的Stats來發現小表,並主動採用Hash Join、最佳化Join Order、減少Shuffle和縮短執行的Pipeline等方法,實現查詢最佳化。

    SET odps.meta.exttable.stats.onlinecollect=true;
    SELECT * FROM <tablename>;
  • 外表Split最佳化

    通過設定split size參數調整單個並發處理的資料大小,從而最佳化查詢效率。其中split size的設定有如下影響。

    • 表資料量非常大,每次讀取的資料太少,會導致split數太多,並行度多大,Instance大多數時間在排隊等資源。

    • 表資料量非常小,每次讀取的資料太多,會導致split數太少,並發不夠,大部分資源都空閑。

    SET odps.stage.mapper.split.size=<value>;
    SELECT * FROM <tablename>;

將資料寫入OSS

與讀取OSS資料類似,MaxCompute支援將內部表資料或處理外部表格得到的資料寫入OSS。

文法說明

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

參數名

是否必填

描述

table_name

要寫入的外表名稱。

select_statement

SELECT子句,從源表中查詢需要插入目標表的資料。 如果目標表只有一級動態分區,則SELECT子句的最後一個欄位值即為目標表的動態分區值。源表SELECT的值和輸出分區的值的關係是由欄位順序決定,並不是由列名稱決定的。當源表的欄位與目標表欄位順序不一致時,建議您按照目標表順序在select_statement語句中指定欄位。

from_statement

FROM子句,表示資料來源。例如,要讀取的內部表名稱。

如果需要向動態分區中插入資料,請參考插入或覆寫動態分區資料(DYNAMIC PARTITION)

注意事項

  • 如果INSERT OVERWRITE ... SELECT ... FROM ...;操作在來源資料表from_tablename上分配了1000個Mapper,則最後將產生1000個TSV或CSV檔案。

  • 可以通過MaxCompute提供的配置控制組建檔案的數量。

    • Outputer在Mapper裡:通過odps.stage.mapper.split.size控制Mapper的並發數,從而調整產生的檔案數量。

    • Outputer在Reduce或Joiner裡:分別通過odps.stage.reducer.numodps.stage.joiner.num來調整產生的檔案數量。

通過OSS分區上傳功能將資料寫入OSS

當需要將資料以開源格式寫入OSS時,可以通過基於開來源資料解析器建立的OSS外部表格及OSS的分區上傳功能,執行INSERT操作將資料寫入OSS。

開啟OSS分區上傳功能設定如下:

情境

命令

在Project層級設定

整個Project生效。

setproject odps.sql.unstructured.oss.commit.mode =true;

在Session層級設定

只對當前任務生效。

set odps.sql.unstructured.oss.commit.mode =true;

屬性odps.sql.unstructured.oss.commit.mode預設取值為false,不同取值時的實現原理如下:

取值

原理

false

MaxCompute寫入到OSS外部表格的資料,會儲存在LOCATION目錄下的.odps檔案夾中。.odps檔案夾中維護了一個.meta檔案,用於保證MaxCompute資料的一致性。.odps的內容只有MaxCompute能正確處理,在其他資料處理引擎中可能無法正確解析,從而報錯。

true

MaxCompute使用分區上傳功能,相容其他資料處理引擎。以two-phase commit的方式保證資料的一致性,同時也不會有.odps目錄以及.meta檔案。

匯出檔案管理

參數說明

當需要為寫入OSS的資料檔案添加首碼、尾碼或者副檔名時,可以通過如下參數設定。

property_name

使用情境

說明

property_value

預設值

odps.external.data.output.prefix

(相容odps.external.data.prefix)

當需要添加輸出檔案的自訂首碼名時,請添加該屬性。

  • 僅包含數字,字母,底線(a-z, A-Z, 0-9, _)。

  • 長度在1-10之間。

合格字元組合,例如'mc_'

odps.external.data.enable.extension

當需要顯示輸出檔案的副檔名時,請添加該屬性。

True表示顯示輸出檔案的副檔名,反之不顯示副檔名。

  • True

  • False

False

odps.external.data.output.suffix

當需要添加輸出檔案的自訂尾碼名時,請添加該屬性。

僅包含數字,字母,底線(a-z, A-Z, 0-9, _)。

合格字元組合,例如'_hangzhou'

odps.external.data.output.explicit.extension

當需要添加輸出檔案的自訂副檔名時,請添加該屬性。

  • 僅包含數字,字母,底線(a-z, A-Z, 0-9, _)。

  • 長度在1-10之間。

  • 優先順序高於參數odps.external.data.enable.extension

合格字元組合,例如"jsonl"

使用樣本

  1. 為寫入OSS的檔案自訂首碼為test06_,DDL如下所示:

    CREATE EXTERNAL TABLE  <mc_oss_extable_name>
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitute DOUBLE,
      locationLongitude DOUBLE,
      recordTime STRING,
      direction STRING
    )
    ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
    WITH serdeproperties (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    ) 
    STORED AS textfile
    LOCATION 'oss://oss-cn-beijing-internal.aliyuncs.com/***/'
    TBLPROPERTIES (
    -- 設定自訂首碼。
        'odps.external.data.output.prefix'='test06_') 
    ;
    
    -- 向外表寫入資料。
    INSERT INTO  <mc_oss_extable_name> VALUES (1,32,76,1,63.32106,-92.08174,'9/14/2014 0:10','NW');

    寫入後產生的檔案如下圖所示:

    image

  2. 為寫入OSS的檔案自訂尾碼為_beijing,DDL如下所示:

    CREATE EXTERNAL TABLE <mc_oss_extable_name>
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitute DOUBLE,
      locationLongitude DOUBLE,
      recordTime STRING,
      direction STRING
    )
    ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
    WITH serdeproperties (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    ) 
    STORED AS textfile
    LOCATION 'oss://oss-cn-beijing-internal.aliyuncs.com/***/'
    TBLPROPERTIES (
    -- 設定自訂尾碼。
        'odps.external.data.output.suffix'='_beijing') 
    ;
    
    -- 向外表寫入資料。
    INSERT INTO <mc_oss_extable_name> VALUES (1,32,76,1,63.32106,-92.08174,'9/14/2014 0:10','NW');

    寫入後產生的檔案如下圖所示:

    image

  3. 為寫入OSS的檔案自動產生副檔名,DDL如下所示:

    CREATE EXTERNAL TABLE <mc_oss_extable_name>
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitute DOUBLE,
      locationLongitude DOUBLE,
      recordTime STRING,
      direction STRING
    )
    ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
    WITH serdeproperties (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    ) 
    STORED AS textfile
    LOCATION 'oss://oss-cn-beijing-internal.aliyuncs.com/***/'
    TBLPROPERTIES (
    -- 自動產生副檔名。
        'odps.external.data.enable.extension'='true') 
    ;
    
    -- 向外表寫入資料。
    INSERT INTO <mc_oss_extable_name> VALUES (1,32,76,1,63.32106,-92.08174,'9/14/2014 0:10','NW');

    寫入後產生的檔案如下圖所示:

  4. 為寫入OSS的檔案自訂副檔名jsonl,DDL如下所示:

    CREATE EXTERNAL TABLE <mc_oss_extable_name>
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitute DOUBLE,
      locationLongitude DOUBLE,
      recordTime STRING,
      direction STRING
    )
    ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
    WITH serdeproperties (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    ) 
    STORED AS textfile
    LOCATION 'oss://oss-cn-beijing-internal.aliyuncs.com/***/'
    TBLPROPERTIES (
    -- 自訂副檔名。
       'odps.external.data.output.explicit.extension'='jsonl') 
    ;
    
    -- 向外表寫入資料。
    INSERT INTO <mc_oss_extable_name> VALUES (1,32,76,1,63.32106,-92.08174,'9/14/2014 0:10','NW');

    寫入後產生的檔案如下圖所示:

    image.png

  5. 為寫入OSS的檔案設定首碼為mc_,尾碼為_beijing,副檔名為jsonl,DDL如下所示:

    CREATE EXTERNAL TABLE <mc_oss_extable_name>
    (
      vehicleId INT,
      recordId INT,
      patientId INT,
      calls INT,
      locationLatitute DOUBLE,
      locationLongitude DOUBLE,
      recordTime STRING,
      direction STRING
    )
    ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
    WITH serdeproperties (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    ) 
    STORED AS textfile
    LOCATION 'oss://oss-cn-beijing-internal.aliyuncs.com/***/'
    TBLPROPERTIES (
        -- 自訂首碼。
        'odps.external.data.output.prefix'='mc_', 
        -- 自訂尾碼。
        'odps.external.data.output.suffix'='_beijing', 
        -- 自訂副檔名。
        'odps.external.data.output.explicit.extension'='jsonl') 
    ;  
    
    -- 向外表寫入資料。
    INSERT INTO <mc_oss_extable_name> VALUES (1,32,76,1,63.32106,-92.08174,'9/14/2014 0:10','NW');

    寫入後產生的檔案如下圖所示:

    image.png

以動態分區形式寫出大檔案

業務情境

需要以分區的形式將上遊表的計算結果匯出到OSS上,並寫出為大檔案(如4G)時。

通過配置odps.adaptive.shuffle.desired.partition.size參數(單位MB),可以控制下遊每個Reducer讀取的資料量及輸出檔案的大小。但是由於輸出大檔案會導致並行度降低,進而延長整體執行時間。

參數說明

-- 必須開啟動態分區能力。
set odps.sql.reshuffle.dynamicpt=true; 	

-- 設定期望每個reducer消費的資料,假設希望每個檔案是4G。
set odps.adaptive.shuffle.desired.partition.size=4096;	

使用樣本

向OSS寫出大小約4G的json檔案。

  1. 準備測試資料。公用資料集的表bigdata_public_dataset.tpcds_1t.web_sales,約30G(以壓縮的形式儲存在MaxCompute上,匯出後儲存會增大)。

  2. 建立JSON外部表格。

    -- 樣本表名:json_ext_web_sales
    CREATE EXTERNAL TABLE  json_ext_web_sales(
        c_int INT ,
        c_string STRING 
    )
    PARTITIONED BY (pt STRING)
    ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
    WITH serdeproperties (
      'odps.properties.rolearn'='acs:ram::<uid>:role/aliyunodpsdefaultrole'
    )
    STORED AS textfile
    LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/oss-mc-test/demo-test/';
  3. 未設定任何參數,將測試表以動態分區的形式寫入JSON外部表格。

    -- 開啟三層文法開關。
    set odps.namespace.schema=true;
    
    -- 向JSON外表以動態分區的形式寫入。
    INSERT OVERWRITE json_ext_web_sales 
    PARTITION(pt) 
    SELECT CAST(ws_item_sk AS INT) AS c_int, 
           CAST(ws_bill_customer_sk AS string) AS c_string , 
          COALESCE(CONCAT(ws_bill_addr_sk %2, '_', ws_promo_sk %3),'null_pt') AS pt 
    FROM  bigdata_public_dataset.tpcds_1t.web_sales;

    OSS上儲存的檔案如下圖所示:

    image

  4. 加上輸出大檔案的參數odps.adaptive.shuffle.desired.partition.size,將測試表以動態分區的形式寫入JSON外部表格。

    -- 開啟三層文法開關。
    set odps.namespace.schema=true;
    
    -- 必須開啟動態分區能力。
    set odps.sql.reshuffle.dynamicpt=true; 	
    
    -- 設定期望每個reducer消費的資料,假設希望每個檔案是4G。
    set odps.adaptive.shuffle.desired.partition.size=4096;	
    
    -- 向JSON外表以動態分區的形式寫入。
    INSERT OVERWRITE json_ext_web_sales 
    PARTITION(pt) 
    SELECT CAST(ws_item_sk AS INT) AS c_int, 
           CAST(ws_bill_customer_sk AS string) AS c_string , 
          COALESCE(CONCAT(ws_bill_addr_sk %2, '_', ws_promo_sk %3),'null_pt') AS pt 
    FROM  bigdata_public_dataset.tpcds_1t.web_sales;

    OSS上儲存的檔案如下圖所示:

從OSS匯入或匯出到OSS

  • LOAD命令:將外部儲存OSS上的資料匯入MaxCompute的表或表的分區中。

  • UNLOAD命令:將MaxCompute專案中的資料匯出至外部儲存OSS,以供其他計算引擎使用。

附錄:準備樣本資料

  1. 準備OSS目錄

    提供的樣本資料資訊如下:

    • oss_endpointoss-cn-hangzhou-internal.aliyuncs.com,即華東1(杭州)。

    • Bucket名稱oss-mc-test

    • 目錄名稱Demo1/Demo2/Demo3/SampleData/

  2. 非分區表資料

    Demo1/目錄下上傳的檔案為vehicle.csv,檔案中包含的資料資訊如下。Demo1/目錄用於和通過內建文本資料解析器建立的非分區表建立映射關係。

    1,1,51,1,46.81006,-92.08174,9/14/2014 0:00,S
    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,4,30,1,46.81006,-92.08174,9/14/2014 0:00,W
    1,5,47,1,46.81006,-92.08174,9/14/2014 0:00,S
    1,6,9,1,46.81006,-92.08174,9/15/2014 0:00,S
    1,7,53,1,46.81006,-92.08174,9/15/2014 0:00,N
    1,8,63,1,46.81006,-92.08174,9/15/2014 0:00,SW
    1,9,4,1,46.81006,-92.08174,9/15/2014 0:00,NE
    1,10,31,1,46.81006,-92.08174,9/15/2014 0:00,N
  3. 分區表資料

    Demo2/目錄下包含五個子目錄direction=N/direction=NE/direction=S/direction=SW/direction=W/,分別上傳的檔案為vehicle1.csv、vehicle2.csv、vehicle3.csv、vehicle4.csv和vehicle5.csv,檔案中包含的資料資訊如下。Demo2/目錄用於和通過內建文本資料解析器建立的分區表建立映射關係。

    --vehicle1.csv
    1,7,53,1,46.81006,-92.08174,9/15/2014 0:00
    1,10,31,1,46.81006,-92.08174,9/15/2014 0:00
    
    --vehicle2.csv
    1,2,13,1,46.81006,-92.08174,9/14/2014 0:00
    1,3,48,1,46.81006,-92.08174,9/14/2014 0:00
    1,9,4,1,46.81006,-92.08174,9/15/2014 0:00
    
    --vehicle3.csv
    1,6,9,1,46.81006,-92.08174,9/15/2014 0:00
    1,5,47,1,46.81006,-92.08174,9/14/2014 0:00
    1,6,9,1,46.81006,-92.08174,9/15/2014 0:00
    
    --vehicle4.csv
    1,8,63,1,46.81006,-92.08174,9/15/2014 0:00
    
    --vehicle5.csv
    1,4,30,1,46.81006,-92.08174,9/14/2014 0:00
  4. 壓縮資料

    Demo3/目錄下上傳的檔案為vehicle.csv.gz,壓縮包內檔案為vehicle.csv,與Demo1/目錄下的檔案內容相同,用於和攜帶壓縮屬性的OSS外部表格建立映射關係。

  5. 自訂解析器資料

    SampleData/目錄下上傳的檔案為vehicle6.csv,檔案中包含的資料資訊如下。SampleData/目錄用於和通過開來源資料解析器建立的OSS外部表格建立映射關係。

    1|1|51|1|46.81006|-92.08174|9/14/2014 0:00|S
    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|4|30|1|46.81006|-92.08174|9/14/2014 0:00|W
    1|5|47|1|46.81006|-92.08174|9/14/2014 0:00|S
    1|6|9|1|46.81006|-92.08174|9/14/2014 0:00|S
    1|7|53|1|46.81006|-92.08174|9/14/2014 0:00|N
    1|8|63|1|46.81006|-92.08174|9/14/2014 0:00|SW
    1|9|4|1|46.81006|-92.08174|9/14/2014 0:00|NE
    1|10|31|1|46.81006|-92.08174|9/14/2014 0:00|N

常見問題

通過外部表格處理OSS資料時,報錯Inline data exceeds the maximun allowed size,如何解決?

  • 問題現象

    處理OSS資料時,報錯Inline data exceeds the maximum allowed size

  • 產生原因

    OSS Store對於每一個小檔案有一個大小限制,如果超過3 GB則報錯。

  • 解決措施

    針對該問題,您可以通過調整以下兩個屬性進行處理。其原理是通過屬性值調整執行計畫,控制每個Reducer寫入外部表格OSS的資料大小,使得OSS Store檔案不超過3 GB的限制。

    set odps.sql.mapper.split.size=256; #調整每個Mapper讀取資料的大小,單位是MB。
    set odps.stage.reducer.num=100; #調整Reduce階段的Worker數量。

在MaxCompute上訪問OSS外部表格,編寫UDF本地測試通過,上傳後報錯記憶體溢出,如何解決?

  • 問題現象

    在MaxCompute上訪問OSS外部表格,編寫UDF本地測試通過,上傳後返回如下報錯。

    FAILED: ODPS-0123131:User defined function exception - Traceback:
    java.lang.OutOfMemoryError: Java heap space        

    設定如下參數後已耗用時間增加但依然報錯。

    set odps.stage.mapper.mem = 2048; 
    set odps.stage.mapper.jvm.mem = 4096;       
  • 產生原因

    外部表格的對象檔案太多,記憶體佔用過大且未設定分區。

  • 解決措施

    • 使用小資料量查詢。

    • 將對象檔案進行分區,以減少記憶體佔用。

如何通過OSS外部表格將多個小檔案輸出為一個檔案?

通過Logview日誌,查看SQL的執行計畫中最後一個是Reducer還是Joiner。

  • 如果是Reducer,則執行語句set odps.stage.reducer.num=1;

  • 如果是Joiner,則執行語句set odps.stage.joiner.num=1;

讀取OSS外部表格時報錯Couldn't connect to server,如何解決?

  • 問題現象

    讀取OSS外部表格的資料時,報錯ODPS-0123131:User defined function exception - common/io/oss/oss_client.cpp(95): OSSRequestException: req_id: , http status code: -998, error code: HttpIoError, message: Couldn't connect to server

  • 產生原因

    • 原因一:建立OSS外部表格時,oss_location地址中的oss_endpoint使用了公網地址,未使用內網地址。

    • 原因二:建立OSS外部表格時,oss_location地址中的oss_endpoint使用了其他Region的地址。

  • 解決措施

    • 對於原因一:

      您需要核查OSS外部表格的建表語句中oss_location參數的oss_endpoint是否為內網地址,如果是公網地址則需要修改為內網地址,具體參數資訊請參見參數說明

      例如,使用者在印尼(雅加達)地區,使用了oss://oss-ap-southeast-5.aliyuncs.com/<bucket>/....地址建立外部表格,應該改為對應的內網地址oss://oss-ap-southeast-5-internal.aliyuncs.com/<bucket>/....

    • 對於原因二:

      您需要核查OSS外部表格的建表語句中,oss_location參數的oss_endpoint是否為要訪問的Region的Endpoint,更多OSS傳統網路網域名稱資訊,請參見OSS地區和訪問網域名稱

建立OSS外部表格時報錯Network is unreachable (connect failed) ,如何解決?

  • 問題現象

    建立OSS外部表格時,報錯ODPS-0130071:[1,1] Semantic analysis exception - external table checking failure, error message: Cannot connect to the endpoint 'oss-cn-beijing.aliyuncs.com': Connect to bucket.oss-cn-beijing.aliyuncs.com:80 [bucket.oss-cn-beijing.aliyuncs.com] failed: Network is unreachable (connect failed)

  • 產生原因

    建立OSS外部表格時,oss_location地址中的oss_endpoint使用了公網地址,未使用內網地址。

  • 解決措施

    你需要核查OSS外部表格的建表語句中,oss_location參數的oss_endpoint是否為內網地址。如果是公網地址,則需要修改為內網地址,具體參數資訊請參見參數說明

    例如,使用者在華北2(北京)地區,使用了oss://oss-cn-beijing.aliyuncs.com/<bucket>/....地址建立外部表格,應該改為對應的內網地址oss://oss-cn-beijing-internal.aliyuncs.com/<bucket>/....

基於OSS外部表格執行SQL作業時,運行慢,如何解決?

  • OSS外部表格中的GZ壓縮檔讀取慢

    • 問題現象

      使用者建立了一個OSS外部表格,資料來源為OSS中的GZ壓縮檔,大小為200 GB。在讀取資料過程中執行緩慢。

    • 產生原因

      由於Map端執行計算的Mapper數量過少,所以SQL處理慢。

    • 解決措施

      • 對於結構化資料,您可以設定以下參數調整單個Mapper讀取資料量的大小,加速SQL執行。

        set odps.sql.mapper.split.size=256; #調整每個Mapper讀取Table資料的大小,單位是MB。       
      • 對於非結構化資料,您需要查看OSS外部表格路徑下的OSS檔案是否只有1個。如果只有1個,由於壓縮方式下的非結構化資料不支援拆分,所以只能生產1個Mapper,導致處理速度較慢。建議您在OSS對應的外部表格路徑下,將OSS大檔案拆分為小檔案,從而增加讀取外部表格產生的Mapper數量,提升讀取速度。

  • 使用SDK搜尋MaxCompute外部表格資料速度慢

    • 問題現象

      使用SDK搜尋MaxCompute外部表格資料速度慢。

    • 解決措施

      外部表格僅支援全量搜尋,所以較慢,建議您改用MaxCompute內部表。

通過OSS分區上傳功能將資料寫入OSS情境下,舊資料被刪除,但是新資料未寫入,如何解決?

  • 問題現象

    insert overwrite操作環境,在極端情況下如果作業運行失敗會出現與預期不一致的問題,表現為舊資料被刪除,但是新資料並沒有寫入。

  • 產生原因

    新寫入的資料因為極低機率的硬體故障或中繼資料更新失敗等原因沒有成功寫入目標表,且OSS的刪除操作不支援復原,導致被刪除的舊資料無法恢複。

  • 解決措施

    • 如果基於舊資料再覆寫OSS外部表格,例如insert overwrite table T select * from table T;,需要提前做好OSS資料備份,作業運行失敗時,再基於備份的舊資料覆寫OSS外部表格。

    • 如果insert overwrite作業可以重複提交,當作業運行失敗時重新提交作業即可。

相關文檔