MaxCompute推出了Object Table功能,該功能支援數倉計算引擎訪問資料湖儲存中的非結構化資料及其元資訊。本文為您介紹Object Table相關的命令文法和樣本。
背景資訊
許多AI流程環節需要熟悉資料和業務的數倉開發人員,利用巨量資料平台提供的低成本大規模算力對大模型進行資料預先處理或非結構化資料處理。這些計算過程及其結果將與數倉或資料湖中的資料進行互動。
使用SQL處理非結構化資料存在以下問題。
巨量資料SQL引擎在讀取Object Storage Service檔案時並不感知對象的大小,因此缺乏依據來最佳化執行計畫。這使得控制並發或自動啟動合適的並發變得困難。同時,由於無法有效下推過濾條件,在資料扭曲的情況下,無法充分發揮算力的優勢。
Object Storage Service的元資訊讀取效能不足,每次查詢均需遠端存取儲存服務,導致延時較高。
只能在UDTF中以單進程串列方式擷取Object Storage Service的檔案清單,導致資料讀取效能較差。
需要在使用者自訂函數(UDF)中自主實現許可權打通的邏輯,並且需要實現UDF與儲存服務等之間的網路連接邏輯。
UDF在非結構化資料處理方面的能力不足,傳統資料倉儲缺乏靈活且安全的自訂鏡像上傳功能,同時也缺乏UDF的安全運行環境。此外,遠程調用需要與分散式運算服務進行並發對接。
功能說明
MaxCompute推出了Object Table功能,該功能支援數倉計算引擎訪問資料湖儲存中的非結構化資料及其元資訊,具備以下能力:
支援引擎以表的形式讀取OSS檔案元資訊。
基於Metadata Table能力,以版本化方式緩衝OSS檔案的各種元資訊,後續SQL引擎能基於Metadata Table實現有效查詢最佳化,包括資料過濾和條件下推等功能。
基於內建文檔函數以多種方式讀取非結構化資料檔案內容。
MaxCompute SQL引擎基於Object Table元資訊進行並發切分,啟動大規模分散式運算能力,以提高資料讀取和處理的效率。
支援使用者上傳自訂鏡像構建UDF,並處理引擎讀取的非結構化資料。
支援引擎處理非結構化資料,產生結構化資料結果並將其寫入資料倉儲的內部表和外部表格,後續支援產生非結構化資料結果,並通過Object Table寫回Object Storage Service服務。
支援Python生態系統的Maxframe引擎。
使用限制
MaxCompute專案需要支援Schema功能,詳情請參見Schema功能開啟。
MaxCompute需要支援2.0資料類型系統。
Object Table暫不支援分區。
費用說明
Object Table是OSS上檔案元資訊的集合,因此會對重新整理存入Object Table的中繼資料收取儲存費用,詳情請參見儲存費用。由於OSS上的檔案沒有儲存在MaxCompute內部,MaxCompute不收取儲存費用,具體儲存和訪問資料的費用由OSS儲存服務收取,詳情請參見OSS儲存費用。
在重新整理OSS元資訊的抽取任務中,掃描的每個檔案的
inputsize是一個與元資訊相關的值,而與檔案的實際大小無關。因此,重新整理計算任務的整體費用與OSS上對應檔案的實際大小無關,而是與檔案數量相關。詳情請參見SQL外部表格計費。使用Object Table及其相關中繼資料進行OSS非結構化資料的分析與提取,並進行相應處理,會產生計算費用。
在隨用隨付模式下,對Object Table的中繼資料分析按照內表進行計費,請參見SQL標準計費。而對OSS非結構化資料的內容進行處理則按照外表進行計費,請參見SQL外部表格計費。
在訂用帳戶付費模式下,均使用訂用帳戶的預付費資源,請參見計算費用(訂用帳戶)。
建立OBJECT TABLE
文法
CREATE OBJECT TABLE [IF NOT EXISTS] <objecttable_name>
WITH SERDEPROPERTIES ('<key>' = '<value>')
LOCATION '<location>'
[TBLPROPERTIES ('<key>' = '<value>')]
[COMMENT '<comment>']
;Object Table需要在內部專案支援Schema模式下使用,同時開啟Schema文法開關。
Object Table不需要定義列,中繼資料資訊列由系統提供。
參數說明
參數 | 是否必填 | 說明 |
objecttable_name | 必填。 | 表名。 |
SERDEPROPERTIES ('<key>'='<value>') | 必填。 | 支援填寫RAM角色認證資訊。不填則預設使用當前阿里雲帳號(主帳號)的名為 例如: 使用前,請確保已完成
說明 當MaxCompute的ProjectOwner為OSS雲帳號時,才可以執行一鍵授權。 |
location | 必填。 |
|
TBLPROPERTIES ('<key>'='<value>') | 可選。 |
|
comment | 可選。 | 表注釋內容。 |
樣本
SET odps.namespace.schema=true;
CREATE OBJECT TABLE ot_demo_day
WITH serdeproperties (
'odps.properties.rolearn'='acs:ram::xxxxxx:role/aliyunodpsdefaultrole')
LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/odps-external-****/ottest/';查看OBJECT TABLE屬性
文法
DESC <object_table_name>參數說明
object_table_name:必填,表名。
樣本
DESC ot_demo_day; 返回結果如下。
+------------------------------------------------------------------------------------+
| Owner: ALIYUN$****@test.aliyunid.com |
| Project: test_objecttable |
| Schema: default |
| TableComment: |
+------------------------------------------------------------------------------------+
| CreateTime: 2024-09-02 20:01:56 |
| LastDDLTime: 2024-09-02 20:01:56 |
| LastModifiedTime: 2024-09-02 20:01:56 |
+------------------------------------------------------------------------------------+
| InternalTable: YES | Size: 0 |
+------------------------------------------------------------------------------------+
| Native Columns: |
+------------------------------------------------------------------------------------+
| Field | Type | Label | Comment |
+------------------------------------------------------------------------------------+
| key | varchar(2048) | | The name of the object. |
| size | bigint | | The size of the returned object in bytes. |
| type | varchar(32) | | The type of the object and valid values: Normal, Multipart, Appendable, and Symlink. |
| last_modified | timestamp | | The last modified time of the object. |
| storage_class | varchar(32) | | The storage class of the object. |
| etag | varchar(64) | | The entity tag (ETag). When an object is created, an ETag is created to identify the content of the object. |
| restore_info | varchar(256) | | The restoration status of the object. |
| owner_id | bigint | | The ID of the bucket owner. |
| owner_display_name | varchar(256) | | The display name of the bucket owner. |
+------------------------------------------------------------------------------------+返回結果部分列名說明。
列名 | 類型說明 | 是否支援NULL | 說明 |
key | VARCHAR(2048) 原生長度約束為1023。 | False | 對象在Object Table中的相對路徑名。 |
size | BIGINT | False | 對象的大小,單位為位元組。 |
type | VARCHAR(32) | False | 對象在OSS側的檔案類型:Normal、Multipart、Appendable和Symlink。 |
last_modified | TIMESTAMP_NTZ | False | 對象在OSS上的資料最後變更時間。 |
storage_class | VARCHAR(32) | False | 對象在OSS上的儲存類型。具體類型請參見儲存類型。 |
etag | VARCHAR(64) | False | ETag是在每個Object產生時建立的實體標記(一個簽名資訊),用於標識一個Object的內容在前後兩次更新過程中是否發生變化(但不是唯一性標記)。 |
restore_info | VARCHAR(256) | True | 描述一個對象是否被從冷存中恢複,如果是恢複過程中的對象,則有相關的資訊描述。 |
owner_id | BIGINT | True | 對象的所有者ID。 |
owner_display_name | VARCHAR(256) | True | 對象的所有者的名稱。 |
查看OBJECT TABLE建表語句
文法
SHOW CREATE TABLE <object_table_name>;參數說明
object_table_name:必填,表名。
樣本
SHOW CREATE TABLE ot_demo_day; 返回結果如下。
CREATE OBJECT TABLE IF NOT EXISTS yunqi_object_****.`default`.ot_demo_day
WITH SERDEPROPERTIES (
'serialization.format'='1',
'odps.properties.rolearn'='acs:ram::139699392458****:role/aliyunodpsdefaultrole')
LOCATION
'oss://oss-cn-hangzhou-internal.aliyuncs.com/odps-external-****/ottest/'
TBLPROPERTIES (
'last_modified_time'='1731478307',
'transient_lastDdlTime'='1731478307',
'metadata.cache.mode'='manual',
'metadata.staleness.seconds'='3600');重新整理OBJECT TABLE元資訊
Object Table的真實對象資料存放區於OSS中。在MaxCompute中,對這些對象資料的元資訊進行緩衝,並基於緩衝的中繼資料執行各種查詢和計算。因此,在實際使用Object Table之前,需要對其進行一些緩衝更新操作。可以通過手動重新整理或在建表時配置周期性重新整理參數。
無論是手動重新整理還是周期性重新整理,都是全量重新整理。
手動重新整理
每次重新整理均為全量元資訊同步,您可自主控制重新整理的時機與頻率。
文法
ALTER TABLE <objecttable_name> REFRESH METADATA;參數說明
objecttable_name:必填,表名。
樣本
ALTER TABLE ot_demo_day REFRESH METADATA;
周期性重新整理
如果Object Table映射的OSS目錄中的檔案經常發生變化,可以按周期重新整理中繼資料。只需要在建表時指定相關參數即可,減少維護的成本。
文法
SET odps.namespace.schema=true; SET odps.sql.type.system.odps2 = true; CREATE OBJECT TABLE ot_demo_day WITH serdeproperties ( 'odps.properties.rolearn'='acs:ram::xxxxxx:role/aliyunodpsdefaultrole' ) location 'oss://oss-cn-hangzhou-internal.aliyuncs.com/odps-external-****/ottest/' tblproperties ( 'metadata.cache.mode' = 'periodic', 'metadata.staleness.seconds' = '3600' );參數說明
metadata.staleness.seconds:重新整理周期。對於periodic模式來說,必須要指定這個參數,取值範圍為[1, 604800],表示1秒到1周範圍內。該參數並非強制性保障,調度器將儘可能按照該參數進行執行。metadata.cache.mode:重新整理觸發方式,有兩種選擇。periodic:周期性觸發。manual:手動觸發(預設),您可以自主控制觸發時機。
查看重新整理任務
可以通過如下命令查看歷史的重新整理任務狀態。
SHOW refresh task history FOR object TABLE <object_table_name>;參數說明
<object_table_name>必須是一個Object Table;
傳回值:執行重新整理的執行個體ID(InstanceId)、開始時間(CreateTime)、結束時間(EndTime)、執行狀態(Status)。
當執行狀態(Status)值為Failed時,可通過
wait InstanceId;列印log view查看報錯明細。
樣本
-- 查看Object Table的歷史重新整理任務 SHOW refresh task history for object table ot_demo_day04; -- 返回結果。 ID = 20260105*******f +---------------------------------------------------------------------------------------------------+ | Project: test_project | | Schema: default | | Task: *** | +---------------------------------------------------------------------------------------------------+ | History: | +---------------------------------------------------------------------------------------------------+ | InstanceId | CreateTime | EndTime | Status | +---------------------------------------------------------------------------------------------------+ | 20260105******************ks | 2026-01-05 14:12:00 | 2026-01-05 14:12:04 | Terminated | | 20260105******************y3 | 2026-01-05 14:10:00 | 2026-01-05 14:10:03 | Terminated | +---------------------------------------------------------------------------------------------------+ OK
查詢OBJECT TABLE
Object Table擷取了OSS目錄中檔案的元資訊,您可以通過查詢Object Table明細來瀏覽這些元資訊,也可以使用SQL語句對元資訊進行過濾、匹配等計算,包括但不限於Aggregation、Join、Window、Order By、Limit等。
文法
SELECT * FROM <object_table_name>;參數說明
object_table_name:必填,表名。
樣本
-- 您可以查詢上傳至指定OSS對象目錄下的資料,若資料量大,您可以查看5條。
SELECT * FROM ot_demo_day [limit 5];查詢對象內容進行業務計算
查詢過程本質上僅針對對象的元資訊進行相關計算,並不涉及對象的實際內容。然而,實際的計算過程需要讀取對象的真實內容。MaxCompute內建了下載函數,以便使用者能夠將其整合到實際的計算過程中。
GET_DATA_FROM_OSS函數文法
GET_DATA_FROM_OSS函數用於讀取一個對象的部分或全部內容,並以二進位形式返回。
BINARY GET_DATA_FROM_OSS (
STRING <full_object_table_name>,
STRING <key>
[, BIGINT <offset>]
[, BIGINT <length>]
[, STRING <object_not_found_policy>]
)參數說明
參數 | 是否必填 | 資料類型 | 說明 | 預設值 |
full_object_table_name | 是 | STRING | 三層模型下,完整的OBJECT TABLE路徑,包括Project和Schema名稱,如 如果在建表時選擇了RoleARN的認證方式,該參數將協助使用者自動產生訪問OSS的STS Token。 | 無 |
key | 是 | STRING | 即被訪問對象在該Object Table中的名稱。詳情請參見查看OBJECT TABLE屬性返回結果中的key參數說明。 | 無 |
offset | 否 | BIGINT | 表示讀取對象內容的起始位置,取值大於等於0。 | 預設為0,即從頭開始讀取。 |
length | 否 | BIGINT | 需要讀取的位元組數。 | 預設值為-1,即不限制長度。 |
object_not_found_policy | 否 | STRING | 表示快取資料中存在某個對象的key,但在實際的OSS中該對象已不存在時,MaxCompute返回當前函數調用結果的方式。取值如下:
| 預設值為OUTPUT_NULL。 |
樣本一
如果需要將GET_DATA_FROM_OSS函數的結果輸出為STRING類型,可以嵌套一層STRING函數。
SELECT STRING(
GET_DATA_FROM_OSS('<project_name>.default.ot_demo_day', key, 0, -1, 'OUTPUT_NULL')
)
FROM ot_demo_day;樣本二
讀取Object Table的全部內容,並以二進位形式返回。預設Object Table的完整路徑為<project_name>.default.ot_demo_day,不同參數組合方式如下。
-- 最完整形式。
SELECT GET_DATA_FROM_OSS('<project_name>.default.ot_demo_day', key, 0, -1, 'OUTPUT_NULL') FROM ot_demo_day;
-- 以下寫法均與get_data_from_oss('<project_name>.default.ot_demo_day', key, 0, -1, 'OUTPUT_NULL')等價。
SELECT GET_DATA_FROM_OSS('<project_name>.default.ot_demo_day', key) FROM ot_demo_day;
SELECT GET_DATA_FROM_OSS('<project_name>.default.ot_demo_day', key, 0) FROM ot_demo_day;
SELECT GET_DATA_FROM_OSS('<project_name>.default.ot_demo_day', key, 0, -1) FROM ot_demo_day;
SELECT GET_DATA_FROM_OSS('<project_name>.default.ot_demo_day', key, 'OUTPUT_NULL') FROM ot_demo_day;
SELECT GET_DATA_FROM_OSS('<project_name>.default.ot_demo_day', key, 0, 'OUTPUT_NULL') FROM ot_demo_day;使用查詢最佳化技術提升效能
預設情況下,在MaxCompute的SQL中訪問某張表時,將根據該表的記錄行數、記錄的位元組數以及總的計算資源(受限於使用者的配額配置)進行合理且均勻的切片處理。此舉旨在為不同的分區提供並行計算能力,從而有效控制並行任務中的長尾問題,提升整體查詢效能。
這種切片方式對於需要下載對象表中對象內容以進行記憶體計算的SQL不太適用,效能表現並不是最佳方案,I/O操作容易成為瓶頸,從而導致長尾問題。考慮以下案例:
key | size |
a0000.jpg | 10MB |
a0001.jpg | 10MB |
a0002.jpg | 10MB |
…… | …… |
a1022.jpg | 10MB |
a1023.jpg | 10MB |
b.avi | 10GB |
假設我們僅有兩個工作資源可用,按照普通內表的處理方式,以行數或記錄位元組進行切片,我們可能會切出兩個split對象,分別是split1([a0000.jpg ~ a0511.jpg])和split2([a0512.jpg ~ a1023.jpg, b.avi])。實際的split1所需下載的資料量為10 MB * 512 = 5 GB,而split2所需下載的資料量為5 GB + 10 GB=15 GB。因此,split2對應的計算量明顯高於split1,導致出現嚴重的長尾現象。
真正合理的邏輯是:當使用者的SQL中存在下載對象的需求時,應盡量根據對象的實際大小進行切片,以最大限度地控制長尾問題。如果使用者消費OSS對象資料的邏輯更加耗時,則更需要提供靈活的切片能力。針對上述案例,我們可以拆分出split1:[a0000.jpg ~ a1023.jpg]和split2:[b.avi]兩個切片,這兩個切片的下載量均為10 GB。
為此,MaxCompute的Object Table提供了這樣的能力,並且預設按照對象的實際大小進行切片。該預設值為1GB,使用者可根據需要進行調整,粒度可選擇KB、MB或GB三個層級。
# 預設為1GB,使用者可以自行調整
SET odps.sql.object.table.split.unit.gb = 1;
SELECT get_data_from_oss('project.default.ot_demo_day', key) FROM ot_demo_da WHERE ...
# 或者,使用者選擇MB級控制,優先順序高於GB參數
SET odps.sql.object.table.split.unit.mb = 1;
SELECT get_data_from_oss('project.default.ot_demo_day', key) FROM ot_demo_da WHERE ...
# 或者,使用者選擇KB級控制,優先順序高於GB、MB參數
SET odps.sql.object.table.split.unit.kb = 1;
SELECT get_data_from_oss('project.default.ot_demo_day', key) FROM ot_demo_da WHERE ...若需要在某些情況下主動希望關閉此查詢最佳化方案(該方案會啟動兩個作業,第一個作業負責進行一些預先處理,並且可以在Logview上查看相關資訊),MaxCompute的Object Table表也提供了相應的解決方案:
SET odps.sql.object.table.split.by.object.size.enabled = false;
SELECT get_data_from_oss('project.default.ot_demo_day', key) FROM ot_demo_day WHERE ...刪除OBJECT TABLE
Object Table本身會緩衝使用者的元資訊,這將佔用一定的儲存空間併產生儲存成本。因此,如果使用者在業務上不再需要這些快取資料,可以選擇刪除Object Table表。如後續業務需要重新使用這些資料,可以重建Object Table。
文法
DROP TABLE [IF EXISTS] <object_table_name>; 參數說明
object_table_name:必填,表名。
樣本
DROP TABLE IF EXISTS ot_demo_day;常見問題
ODPS-0010000:System internal error
現象
報錯資訊如下:
ODPS-0010000:System internal error - ActionHandler job failed with failinfo storage service worker error occured: common/io/oss/oss_file_system_cppsdk.cpp(919): OSSRequestException: Status: -50, RequestId: , ErrorCode: ClientError:-50, Message: E_HTTP_ERROR_CONN_REFUSED問題原因
建立Object Table時用了OSS的公網串連地址。
解決方式
建立Object Table時
location參數中的oss_endpoint需要用內網地址,擷取方式見參數說明。
周期性重新整理不成功
現象
當建立Object Table時設定了周期性重新整理的參數,到達重新整理周期後,仍未進行重新整理。
解決方式
請檢查建立Object Table配置的location參數值是否用的是OSS內網網路網域名稱資訊,更多建立Object Table詳情見參數說明。
周期性重新整理任務報錯
報錯資訊
FAILED: ODPS-0010000:System internal error - ActionHandler job failed with failinfo storage service worker error occured: common/io/oss/oss_file_system_cppsdk.cpp(877): OSSRequestException: Status: -50, RequestId: , ErrorCode: ClientError:-50, Message:
解決方式
該報錯為內部錯誤,可以通過工單聯絡MaxCompute支援人員團隊擷取支援。