ApsaraDB for SelectDB支援表函數功能TVF(Table-Value-Function),可以將S3、HDFS等常見遠端儲存中的檔案資料,映射成ApsaraDB for SelectDB中的表,從而對這些檔案資料進行分析。
S3表函數
S3表函數可以讓您像訪問關係型資料庫一樣,讀取並訪問S3相容的Object Storage Service上的檔案內容。目前支援CVS、CSV_with_names、CVS_with_names_and_types、Json、Parquet、ORC檔案格式。
文法
s3(
"uri" = "..",
"s3.access_key" = "...",
"s3.secret_key" = "...",
"s3.region" = "...",
"format" = "csv",
"keyn" = "valuen",
...
);
參數說明
S3 TVF中的每一個參數都是一個"key"="value"
索引值對。常用參數如下:
參數名稱 | 必選 | 參數取值 | 參數說明 |
uri | 是 | 字串。 | 訪問S3的URI。 |
s3.access_key | 是 | 字串。 | 訪問S3的使用者身份密鑰。 |
s3.secret_key | 是 | 字串。 | 訪問S3的使用者加密認證字串。 |
s3.region | 是 | 字串。 | 訪問S3的Object Storage Service所在地區。預設值 |
s3.session_token | 否 說明 若啟用臨時會話驗證,則該參數必選。 | 字串。 | 訪問S3的使用者臨時會話token。 |
use_path_style | 否 |
| S3 SDK預設使用Virtual-hosted Style方式。但某些Object Storage Service系統可能未開啟或不支援Virtual-hosted Style方式的訪問,此時您可以添加 預設為 說明 URI目前支援三種schema:
|
format | 是 |
| 訪問S3上的檔案具體格式。 |
column_separator | 否 | 字串。 | 列分割符,預設為 |
line_delimiter | 否 | 字串。 | 行分割符,預設為 |
compress_type | 否 |
| 檔案的壓縮格式,會根據uri的尾碼自動推斷類型。預設值為UNKNOWN。 |
read_json_by_line | 否 |
| 是否以行為單位讀取JSON資料,預設為true。 |
num_as_string | 否 |
| 數字類型按照String處理,預設為false。 |
fuzzy_parse | 否 |
| 加速JSON資料的匯入效率,預設為false。 |
jsonpaths | 否 | 字串。 | 當匯入資料格式為JSON時,可通過 格式: |
strip_outer_array | 否 |
| 當匯入資料格式為JSON時, 格式: |
json_root | 否 | 字串。 | 當匯入資料格式為JSON時,可以通過 格式: |
path_partition_keys | 否 | 字串。 | 指定檔案路徑中攜帶的分區列名。例如/path/to/city=beijing/date="2023-07-09",則填寫path_partition_keys="city,date"。此時SelectDB將會自動從路徑中讀取相應列名和列值進行匯入。 |
使用樣本
讀取並訪問S3相容的Object Storage Service上的CSV格式檔案,樣本如下。
SELECT * FROM s3("uri" = "http://127.0.0.1:9312/test2/student1.csv", "s3.access_key"= "minioadmin", "s3.secret_key" = "minioadmin", "format" = "csv", "use_path_style" = "true") ORDER BY c1;
配合
DESC FUNCTION
使用,樣本如下。MySQL [(none)]> Desc FUNCTION s3("uri" = "http://127.0.0.1:9312/test2/student1.csv", "s3.access_key"= "minioadmin", "s3.secret_key" = "minioadmin", "format" = "csv", "use_path_style" = "true");
OSS的場合,需採用Virtual-hosted Style方式訪問,樣本如下。
SELECT * FROM s3( "uri" = "http://example-bucket.oss-cn-beijing.aliyuncs.com/your-folder/file.parquet", "s3.access_key"= "ak", "s3.secret_key" = "sk", "format" = "parquet", "use_path_style" = "false");
設定了
"use_path_style"="true"
的場合,將採用path style方式訪問S3,樣本如下。SELECT * FROM s3( "uri" = "https://endpoint/bucket/file/student.csv", "s3.access_key"= "ak", "s3.secret_key" = "sk", "format" = "csv", "use_path_style"="true");
設定了
"use_path_style"="false"
的場合,將採用virtual-hosted style方式訪問S3,樣本如下。SELECT * FROM s3( "uri" = "https://bucket.endpoint/bucket/file/student.csv", "s3.access_key"= "ak", "s3.secret_key" = "sk", "format" = "csv", "use_path_style"="false");
HDFS表函數
HDFS表函數可以讓您像訪問關係表格式資料一樣,讀取並訪問HDFS上的檔案內容。目前支援CVS、CSV_with_names、CVS_with_names_and_types、Json、Parquet、ORC檔案格式。
文法
hdfs(
"uri" = "..",
"fs.defaultFS" = "...",
"hadoop.username" = "...",
"format" = "csv",
"keyn" = "valuen"
...
);
參數說明
HDFS TVF中的每一個參數都是一個"key"="value"
索引值對。常用參數如下:
參數名稱 | 必選 | 參數取值 | 參數說明 |
uri | 是 | 字串。 | 要訪問的HDFS的URI。如果URI路徑不存在或檔案都是空檔案,HDFS TVF將返回空集合。 |
fs.defaultFS | 是 | 字串。 | 要訪問的HDFS的主機和連接埠號碼。 |
hadoop.username | 是 | 字串。 | 要訪問的HDFS使用者名稱,可以是任一字元串,但不可為空。 |
hadoop.security.authentication | 否 |
| 要訪問的HDFS認證方式。可選Simple或者Kerberos。 |
hadoop.kerberos.principal | 否 | 字串。 | 要訪問的HDFS啟用Kerberos驗證的場合,指定Principal。 |
hadoop.kerberos.keytab | 否 | 字串。 | 要訪問的HDFS啟用Kerberos驗證的場合,指定Keytab。 |
dfs.client.read.shortcircuit | 否 |
| HDFS短路本地讀取開關。布爾類型。 |
dfs.domain.socket.path | 否 | 字串。 | 一個指向UNIX域通訊端的路徑,用於DataNode和本地HDFS用戶端通訊。如果在該路徑中出現了字串"_PORT",會被替換成DataNode的TCP連接埠。選擇性參數。 |
dfs.nameservices | 否 | 字串。 | 提供服務的NS邏輯名稱,與core-site.xml裡相應欄位對應。 |
dfs.ha.namenodes.your-nameservices | 否 說明 採用Hadoop HA部署的場合為必選參數。 | 字串。 | dfs.nameservices下的NameNode邏輯名稱。 |
dfs.namenode.rpc-address.your-nameservices.your-namenode | 否 說明 採用Hadoop HA部署的場合為必選參數。 | 字串。 | 每個NameNode監聽的HTTP地址。 |
dfs.client.failover.proxy.provider.your-nameservices | 否 說明 採用Hadoop HA部署的場合為必選參數。 | 字串。 | 用戶端串連可用狀態的NameNode所用的代理類。 |
read_json_by_line | 否 |
| 以行為單位讀取JSON資料,預設為true。 |
num_as_string | 否 |
| 數字類型按照String處理,預設為false。 |
fuzzy_parse | 否 |
| 加速JSON資料的匯入效率,預設為false。 |
jsonpaths | 否 | 字串。 | 當匯入資料格式為JSON時,可通過 格式: |
strip_outer_array | 否 |
| 當匯入資料格式為JSON時, 格式: |
json_root | 否 | 字串。 | 當匯入資料格式為JSON時,可以通過 格式: |
trim_double_quotes | 否 |
| 布爾類型,預設值為false。為true時表示裁剪掉CSV檔案每個欄位最外層的雙引號。 |
skip_lines | 否 | [0-Integer.MaxValue] | 整數類型,預設值為0。含義為跳過CSV檔案的前幾行。當format設定為 |
path_partition_keys | 否 | 字串。 | 指定檔案路徑中攜帶的分區列名。例如/path/to/city=beijing/date="2023-07-09",則填寫path_partition_keys="city,date"。此時SelectDB將會自動從路徑中讀取相應列名和列值進行匯入。 |
使用樣本
讀取並訪問HDFS儲存上的CSV格式檔案,樣本如下。
MySQL [(none)]> SELECT * FROM hdfs(
"uri" = "hdfs://127.0.0.1:842/user/doris/csv_format_test/student.csv",
"fs.defaultFS" = "hdfs://127.0.0.1:8424",
"hadoop.username" = "doris",
"format" = "csv");
-- 返回樣本
+------+---------+------+
| c1 | c2 | c3 |
+------+---------+------+
| 1 | alice | 18 |
| 2 | bob | 20 |
| 3 | jack | 24 |
| 4 | jackson | 19 |
| 5 | liming | 18 |
+------+---------+------+
讀取並訪問HA模式的HDFS儲存上的CSV格式檔案,樣本如下。
MySQL [(none)]> SELECT * FROM hdfs(
"uri" = "hdfs://127.0.0.1:842/user/doris/csv_format_test/student.csv",
"fs.defaultFS" = "hdfs://127.0.0.1:8424",
"hadoop.username" = "doris",
"format" = "csv",
"dfs.nameservices" = "my_hdfs",
"dfs.ha.namenodes.my_hdfs" = "nn1,nn2",
"dfs.namenode.rpc-address.my_hdfs.nn1" = "nanmenode01:8020",
"dfs.namenode.rpc-address.my_hdfs.nn2" = "nanmenode02:8020",
"dfs.client.failover.proxy.provider.my_hdfs" = "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
-- 返回樣本
+------+---------+------+
| c1 | c2 | c3 |
+------+---------+------+
| 1 | alice | 18 |
| 2 | bob | 20 |
| 3 | jack | 24 |
| 4 | jackson | 19 |
| 5 | liming | 18 |
+------+---------+------+
配合DECS FUNCTION
使用,樣本如下。
MySQL [(none)]> DECS FUNCTION hdfs(
"uri" = "hdfs://127.0.0.1:8424/user/doris/csv_format_test/student_with_names.csv",
"fs.defaultFS" = "hdfs://127.0.0.1:8424",
"hadoop.username" = "doris",
"format" = "csv_with_names");
使用方法
本章節將通過S3 TVF舉例說明如何進行檔案分析。
自動推斷檔案列類型
目前支援對Parquet、ORC、CSV、JSON格式進行分析和列類型推斷。
> DESC FUNCTION s3 (
"URI" = "http://127.0.0.1:9312/test2/test.snappy.parquet",
"s3.access_key"= "ak",
"s3.secret_key" = "sk",
"format" = "parquet",
"use_path_style"="true"
);
-- 返回樣本
+---------------+--------------+------+-------+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-------+---------+-------+
| p_partkey | INT | Yes | false | NULL | NONE |
| p_name | TEXT | Yes | false | NULL | NONE |
| p_mfgr | TEXT | Yes | false | NULL | NONE |
| p_brand | TEXT | Yes | false | NULL | NONE |
| p_type | TEXT | Yes | false | NULL | NONE |
| p_size | INT | Yes | false | NULL | NONE |
| p_container | TEXT | Yes | false | NULL | NONE |
| p_retailprice | DECIMAL(9,0) | Yes | false | NULL | NONE |
| p_comment | TEXT | Yes | false | NULL | NONE |
+---------------+--------------+------+-------+---------+-------+
可以看到,對於Parquet檔案,SelectDB會根據檔案內的元資訊自動推斷列類型。
CSV Schema
預設情況下,CSV格式檔案的所有列類型均會被SelectDB視為String。您可以通過csv_schema
屬性單獨指定列名和列類型。SelectDB會使用指定的列類型進行檔案讀取。格式如下:
name1:type1;name2:type2;...
對于格式不匹配的列(例如檔案中實際為字串,您定義為int),或缺失列(比如檔案中實際存在4列,您定義了5列),則這些列將返回null。當前支援的列類型為:
名稱 | 映射類型 |
tinyint | tinyint |
smallint | smallint |
int | int |
bigint | bigint |
largeint | largeint |
float | float |
double | double |
decimal(p,s) | decimalv3(p,s) |
date | datev2 |
datetime | datetimev2 |
char | string |
varchar | string |
string | string |
boolean | boolean |
樣本如下。
s3 (
"URI" = "https://bucket1/inventory.dat",
"s3.access_key"= "ak",
"s3.secret_key" = "sk",
"format" = "csv",
"column_separator" = "|",
"csv_schema" = "k1:int;k2:int;k3:int;k4:decimal(38,10)",
"use_path_style"="true"
)
查詢分析
您可以使用任意的SQL語句,對TVF進行分析,樣本如下。
SELECT * FROM s3(
"URI" = "http://127.0.0.1:9312/test2/test.snappy.parquet",
"s3.access_key"= "ak",
"s3.secret_key" = "sk",
"format" = "parquet",
"use_path_style"="true")
LIMIT 5;
-- 返回樣本
+-----------+------------------------------------------+----------------+----------+-------------------------+--------+-------------+---------------+---------------------+
| p_partkey | p_name | p_mfgr | p_brand | p_type | p_size | p_container | p_retailprice | p_comment |
+-----------+------------------------------------------+----------------+----------+-------------------------+--------+-------------+---------------+---------------------+
| 1 | goldenrod lavender spring chocolate lace | Manufacturer#1 | Brand#13 | PROMO BURNISHED COPPER | 7 | JUMBO PKG | 901 | ly. slyly ironi |
| 2 | blush thistle blue yellow saddle | Manufacturer#1 | Brand#13 | LARGE BRUSHED BRASS | 1 | LG CASE | 902 | lar accounts amo |
| 3 | spring green yellow purple cornsilk | Manufacturer#4 | Brand#42 | STANDARD POLISHED BRASS | 21 | WRAP CASE | 903 | egular deposits hag |
| 4 | cornflower chocolate smoke green pink | Manufacturer#3 | Brand#34 | SMALL PLATED BRASS | 14 | MED DRUM | 904 | p furiously r |
| 5 | forest brown coral puff cream | Manufacturer#3 | Brand#32 | STANDARD POLISHED TIN | 15 | SM PKG | 905 | wake carefully |
+-----------+------------------------------------------+----------------+----------+-------------------------+--------+-------------+---------------+---------------------+
TVF可以出現在SQL中Table能出現的任意位置,如CTE的WITH子句中或者FROM子句中,您可以把檔案當做一張普通的表進行任意分析。
您也可以通過CREATE VIEW
語句為TVF建立一個邏輯視圖。這樣您可以像其他視圖一樣,對這個TVF進行訪問、許可權管理等操作,也可以讓其他使用者訪問這個TVF。
CREATE VIEW v1 AS
SELECT * FROM s3(
"URI" = "http://127.0.0.1:9312/test2/test.snappy.parquet",
"s3.access_key"= "ak",
"s3.secret_key" = "sk",
"format" = "parquet",
"use_path_style"="true");
DESC v1;
SELECT * FROM v1;
GRANT SELECT_PRIV ON db1.v1 TO user1;
資料匯入
配合INSERT INTO SELECT
文法,您可以方便將檔案匯入到SelectDB表中進行更快速的分析,樣本如下。
-- 1. 建立SelectDB內部表
CREATE TABLE IF NOT EXISTS test_table
(
id int,
name varchar(50),
age int
)
DISTRIBUTED BY HASH(id) BUCKETS 4
PROPERTIES("replication_num" = "1");
-- 2. 使用S3 Table Value Function插入資料
INSERT INTO test_table (id,name,age)
SELECT cast(id as INT) as id, name, cast (age as INT) as age
FROM s3(
"uri" = "http://127.0.0.1:9312/test2/test.snappy.parquet",
"s3.access_key"= "ak",
"s3.secret_key" = "sk",
"format" = "parquet",
"use_path_style" = "true");
注意事項
如果S3或HDFS TVF指定的URI匹配不到檔案,或者匹配到的所有檔案都是空檔案,那麼S3或HDFS TVF將會返回空結果集。在這種情況下使用
DESC FUNCTION
查看這個檔案的Schema,會得到一列虛假的列__dummy_col
,可忽略這一列。如果指定TVF的format為CSV,所讀檔案不為空白檔案但檔案第一行為空白,則會產生報誤
The first line is empty, can not parse column numbers
。