本文將進一步為您介紹如何將來自Tablestore(原OTS)的數據納入MaxCompute上的計算生態,實現多種數據源之間的無縫連接。
背景信息
表格存儲(Tablestore)是構建在阿里云飛天分布式系統之上的NoSQL數據存儲服務,提供海量結構化數據的存儲和實時訪問,詳情請參見Tablestore文檔。
您可以通過DataWorks配合MaxCompute對外部表進行可視化的創建、搜索、查詢、配置、加工和分析。詳情請參見外部表。
注意事項
MaxCompute與Tablestore是兩個獨立的大數據計算和存儲服務,所以兩者之間的網絡必須保證連通性。MaxCompute公共云服務訪問Tablestore存儲時,推薦您使用Tablestore私網地址,即Host名以ots-internal.aliyuncs.com作為結尾的地址,例如tablestore://odps-ots-dev.cn-shanghai.ots-internal.aliyuncs.com。
Tablestore與MaxCompute都有其自身的類型系統。在MaxCompute處理Tablestore數據時,兩者之間的數據類型對應關系如下所示。
MaxCompute Type
Tablestore Type
STRING
STRING
BIGINT
INTEGER
DOUBLE
DOUBLE
BOOLEAN
BOOLEAN
BINARY
BINARY
Tablestore外部表不支持cluster屬性。
前提條件
已授權訪問OTS的權限。具體授權操作詳情,請參見OTS的STS模式授權。
已創建Tablestore實例、表和數據。具體操作,請參見通過控制臺使用寬表模型。
創建外部表
MaxCompute通過創建外部表,把對Tablestore表數據的描述引入到MaxCompute的meta系統內部后,即可實現對Tablestore數據的處理。本節通過下述示例為您說明MaxCompute對接Tablestore的一些概念和實現。
創建外部表語句示例如下。
DROP TABLE IF EXISTS ots_table_external;
CREATE EXTERNAL TABLE IF NOT EXISTS ots_table_external
(
odps_orderkey bigint,
odps_orderdate string,
odps_custkey bigint,
odps_orderstatus string,
odps_totalprice double,
odps_createdate timestamp
)
STORED BY 'com.aliyun.odps.TableStoreStorageHandler'
WITH SERDEPROPERTIES (
'tablestore.columns.mapping'=':o_orderkey,:o_orderdate,o_custkey,o_orderstatus,o_totalprice',
'tablestore.table.name'='ots_tpch_orders',
'odps.properties.rolearn'='acs:ram::xxxxx:role/aliyunodpsdefaultrole',
'tablestore.read.mode'='permissive',
'tablestore.corrupt.column'='ColumnName',
'tablestore.timestamp.ticks.unit'='seconds',
'tablestore.column.odps_createdate.timestamp.ticks.unit'='millis',
'tablestore.table.put.row'='true'
)
LOCATION 'tablestore://odps-ots-dev.cn-shanghai.ots-internal.aliyuncs.com';
上述建表語句重點參數介紹如下表所示。
參數 | 是否必填 | 說明 |
com.aliyun.odps.TableStoreStorageHandler | 是 | 是MaxCompute內置的處理Tablestore數據的StorageHandler,定義了MaxCompute和Tablestore的交互,相關邏輯由MaxCompute實現。 |
tablestore.columns.mapping | 是 | 描述MaxCompute將訪問的Tablestore表的列,包括主鍵和屬性列。
|
tablestore.table.name | 是 | 需要訪問的Tablestore表名稱。本文以 |
odps.properties.rolearn | 是 | RAM中AliyunODPSDefaultRole的ARN信息。您可以通過RAM控制臺中的RAM角色管理進行獲取。 |
tablestore.timestamp.ticks.unit | 否 | 表級別時間類型設置。用以指定該外部表中所有Integer的字段都處于同一個時間類型。取值如下:
|
tablestore.column.<col1_name>.timestamp.ticks.unit | 否 | 列級別時間類型設置。用以指定該外部表中列字段的時間類型。取值如下:
說明 tablestore.timestamp.ticks.unit和tablestore.column.<col1_name>.timestamp.ticks.unit都配置時,tablestore.column.<col1_name>.timestamp.ticks.unit參數的優先級更高。 |
tablestore.table.put.row | 否 | 支持指定PutRow的寫入方式。取值說明如下:
說明 可以通過設置以下Flag的參數值指定PutRow的寫入方式,默認值為False。詳情請參見Flag參數列表。
|
tablestore.read.mode | 否 | 當遇到臟數據時行為定義字段,取值說明如下:
關于臟數據處理示例,詳情請參見臟數據處理示例。 |
tablestore.corrupt.column | 否 | 指定臟數據寫入列。
關于臟數據處理示例,詳情請參見臟數據處理示例。 |
LOCATION | 是 | 用來指定Tablestore的Instance名、Endpoint等具體信息。這里的Tablestore數據的安全訪問建立在前文介紹的RAM/STS授權的前提上。 說明 如果您使用公網地址報錯,顯示網絡不同,可嘗試更換為經典網地址。 |
您可以執行如下語句,查看創建好的外部表結構信息。
desc extended <table_name>;
在返回的信息里,除了包含和內部表一樣的基礎信息,Extended Info還包含外部表StorageHandler、Location等信息。
查詢外部表
創建完外部表后,Tablestore的數據便引入到了MaxCompute生態中,即可通過正常的MaxCompute SQL語法訪問Tablestore數據,如下所示。
SELECT odps_orderkey, odps_orderdate, SUM(odps_totalprice) AS sum_total
FROM ots_table_external
WHERE odps_orderkey > 5000 AND odps_orderkey < 7000 AND odps_orderdate >= '1996-05-03' AND odps_orderdate < '1997-05-01'
GROUP BY odps_orderkey, odps_orderdate
HAVING sum_total> 400000.0;
在查詢表或字段時,無需區分大小寫,且不支持強制轉換大小寫。
使用常見的MaxCompute SQL語句訪問Tablestore時,所有的操作細節(例如列名的選擇)是在MaxCompute內部處理完成的。上述SQL示例中,使用的列名是odps_orderkey、odps_totalprice等,而不是原始Tablestore中的主鍵名o_orderkey或屬性列名o_totalprice。這是因為在創建外部表的DDL語句中,已經完成了對應的Mapping。您也可以在創建外部表時,按需選擇保留原始的Tablestore主鍵/列名。
如果您需要對一份數據做多次計算,相比每次從Tablestore去遠程讀數據,更高效的方法是先一次性把需要的數據導入到MaxCompute內部成為一個MaxCompute(內部)表,示例如下。
CREATE TABLE internal_orders AS
SELECT odps_orderkey, odps_orderdate, odps_custkey, odps_totalprice
FROM ots_table_external
WHERE odps_orderkey > 5000 ;
現在internal_orders就是一個MaxCompute表了,也擁有所有MaxCompute內部表的特性,包括高效的壓縮列存儲數據格式、完整的內部宏數據以及統計信息等。同時因為表存儲在MaxCompute內部,所以訪問速度會比訪問外部的Tablestore更快。這種方法非常適用于需要進行多次計算的熱點數據。
MaxCompute導出數據到Tablestore
MaxCompute不會主動創建外部的Tablestore表,所以在對Tablestore表進行數據輸出之前,必須保證該表已經在Tablestore上完成創建(否則將報錯)。
根據上面的操作,您已創建了外部表ots_table_external來打通MaxCompute與Tablestore數據表ots_tpch_orders的鏈路,同時還有一份存儲在MaxCompute內部表internal_orders的數據。現在,如果您需要對internal_orders中的數據進行處理后再寫回Tablestore,則可通過對外部表執行insert overwrite table
操作實現,示例如下。
INSERT OVERWRITE TABLE ots_table_external
SELECT odps_orderkey, odps_orderdate, odps_custkey, CONCAT(odps_custkey, 'SHIPPED'), CEIL(odps_totalprice)
FROM internal_orders;
如果MaxCompute表內數據本身有一定的順序,例如已經按照Primary Key做過一次排序,則在寫入到OTS表時,會導致壓力集中在一個OTS分區上面,無法充分利用分布式寫入的特點。因此,當出現這種情況時,建議您通過distribute by rand()
先將數據打散,示例如下。
INSERT OVERWRITE TABLE ots_table_external
SELECT odps_orderkey, odps_orderdate, odps_custkey, CONCAT(odps_custkey, 'SHIPPED'), CEIL(odps_totalprice)
FROM (SELECT * FROM internal_orders DISTRIBUTE BY rand()) t;
對于Tablestore這種KV數據的NoSQL存儲介質,MaxCompute的輸出將只影響相對應主鍵所在的行,例如示例中只影響所有odps_orderkey + odps_orderdate這兩個主鍵值對應行上的數據。而且在這些Tablestore行上,也只會更新在創建外部表(ots_table_external)時指定的屬性列,而不會修改未在外部表中出現的數據列。
將MaxCompute中的數據寫入OTS時一次不能超過4MB,否則需要用戶剔除掉超大數據再寫入。此時可能會產生報錯。
ODPS-0010000:System internal error - Output to TableStore failed with exception: TableStore BatchWrite request id XXXXX failed with error code OTSParameterInvalid and message:The total data size of BatchWriteRow request exceeds the limit
將數據批量寫入或分行寫入,都算一次操作。詳細描述請參考BatchWriteRow。因此如果批量寫入數據量太大,也可以分行寫入。
將數據批量寫入時請注意不要有重復行,否則可能產生如下報錯。
ErrorCode: OTSParameterInvalid, ErrorMessage: The input parameter is invalid
由于Tablestore是KV存儲,使用
insert overwrite table
寫入數據到Tablestore表,不會清空目標Tablestore表的全部內容,只會覆蓋目標表中Key一致的Value值。
更多詳情請參見MaxCompute訪問TableStore(OTS)數據。
臟數據處理示例
準備Tablestore表
mf_ots_test
和數據。具體操作,請參見通過控制臺使用寬表模型。默認Tablestore的表格數據如下所示。
+----+------+------+ | id | name | desc | +----+------+------+ | 1 | 張三 | 張三的描述 | +----+------+------+
創建MaxCompute外部表。
CREATE EXTERNAL TABLE IF NOT EXISTS mf_ots_external_permi ( id string, name bigint, desc string, corrupt_col string ) STORED BY 'com.aliyun.odps.TableStoreStorageHandler' WITH SERDEPROPERTIES ( 'tablestore.columns.mapping'=':id,name,desc', 'tablestore.table.name'='mf_ots_test', 'tablestore.read.mode'='permissive', 'tablestore.corrupt.column'='corrupt_col', 'odps.properties.rolearn'='acs:ram::139699392458****:role/aliyunodpsdefaultrole' ) LOCATION 'tablestore://santie-doc.cn-shanghai.ots-internal.aliyuncs.com';
執行以下代碼,查詢MaxCompute外部表數據。
---查詢數據 select * from mf_ots_external_permi;
返回結果如下,錯誤字段會以JSON格式寫入至
corrupt_col
列中。-- +------------+------------+------------+-------------+ | id | name | desc | corrupt_col | +------------+------------+------------+-------------+ | 1 | NULL | 張三的描述 | {"name": "\"張三\""} | +------------+------------+------------+-------------+
說明若tablestore.read.mode未配置或配置為permissive,但未配置tablestore.corrupt.column指定臟數據存入列,查詢外表時會報錯
“Columns not match with columns mapping and corrupt column”
。