Hologres V4.1 起支援基於臨時儲存 Stage 的近即時匯入,在分鐘級延遲下平衡吞吐與資源。本文介紹 Stage 能力、管理操作(建立/刪除/查詢)、使用方式(寫入 Stage、從 Stage 寫入內表)及 Arrow 類型映射。
概述
Hologres 目前提供兩種主要的資料匯入模式,分別適用於不同業務情境:
Fixed Plan 即時資料流式寫入:面向資料流式寫入情境。端到端延遲低,通常在毫秒級,可滿足強即時性要求,但資源開銷相對較大。
Bulkload 離線大量匯入:面向高吞吐、大規模資料載入情境,如離線數倉 T+1 資料同步。端到端延遲高,僅能滿足離線業務需求。
若業務存在分鐘級“近即時”需求,離線大量匯入難以滿足時效性;即時資料流式寫入雖可滿足,但會帶來較大寫入資源開銷。Hologres V4.1 版本起,基於臨時儲存 Stage 實現“近即時”資料匯入能力,可有效平衡時效性與資源開銷。
Stage 介紹
Stage 是 Hologres 內部的高效能臨時儲存,具有以下核心特性:
內部託管:由 Hologres 自動管理,無需使用者操作外部儲存。
結構化緩衝:按目標表的 Schema 組織資料,確保類型和格式一致性。
事務安全:支援 ACID 語義,保障寫入過程的可靠性與一致性。
自動合并提交:Spark 等 Connector 支援自動將臨時儲存以最佳化批次方式寫入主儲存,提升效率。
通過以下流程實現 Stage 近即時匯入:
外部資料寫入 Stage。
Stage 資料攢批寫入內表。
內表資料寫入即可見。
Stage 優勢
平衡延遲與吞吐:資料從寫入到可查控制在分鐘級,顯著優於離線大量匯入,同時支援遠高於即時資料流式寫入的吞吐能力。
簡化資料鏈路:資料直接寫入 Hologres 內部 Stage,無外部系統依賴;通過標準 SQL 的 COPY、INSERT 文法及官方 Connector 適配。
提升資源效率:Stage 小檔案自動合并,提升後續讀寫效能;支援 Serverless Computing、獨立計算群組實現 Stage 寫入資源隔離,提升系統穩定性。
適用情境廣泛:Spark Connector、Flink Connector、Holo Client 均支援 Stage 近即時寫入模式。
限制條件
僅支援 Arrow 格式通過 Stage 近即時匯入 Hologres。Arrow 格式與 Hologres 的資料類型映射參見資料類型映射。
許可權說明
SPM 或 SLPM:
建立 Stage:需具備 writer 及以上許可權,或 Superuser。
寫入/刪除/讀取 Stage:需是對應 Stage 的建立者且具備 writer 及以上許可權,或 Superuser。
專家許可權模型:
建立 Stage:需具備
pg_operate_internal_stages角色許可權,或 Superuser。寫入/刪除/讀取 Stage:需是對應 Stage 的建立者且具備
pg_operate_internal_stages角色許可權,或 Superuser。
通過如下命令授予使用者 pg_operate_internal_stages 角色許可權:
-- 授予指定使用者 Stage 操作許可權
-- 可替換變數:<user_name> 替換為實際使用者名稱(如 RAM 子帳號名)
GRANT pg_operate_internal_stages TO "<user_name>";管理 Stage
建立 Stage
命令格式:
-- 建立 Internal Stage
-- 可替換變數:
-- <internal_stage_name>:Stage 名稱,必填,最大 128 字元
-- <group_name>:分組名,可選,預設與 internal_stage_name 相同
-- <ttl_in_seconds>:生命週期(秒),可選,預設 7200,最大 864000
CALL HOLOGRES.HG_CREATE_INTERNAL_STAGE(
'<internal_stage_name>',
['<group_name>'],
['<ttl_in_seconds>']
);參數說明:
參數名 | 是否必填 | 說明 |
internal_stage_name | 必填 | Internal Stage 名稱。支援字母(大小寫敏感)、數字、底線、連字號,最大長度 128 字元。 |
group_name | 非必填 | Stage 所屬分組,用於分類管理。預設同 internal_stage_name。 |
ttl_in_seconds | 非必填 | Stage 生命週期,單位秒,從 last_modified_time(可從系統資料表 |
刪除 Stage
命令格式:
-- 刪除指定 Internal Stage
-- 可替換變數:<internal_stage_name> 替換為要刪除的 Stage 名稱
CALL HOLOGRES.HG_DROP_INTERNAL_STAGE(
'<internal_stage_name>'
);internal_stage_name:必填。Internal Stage 名稱。
查詢 Stage 狀態
可通過系統檢視表 hologres.hg_internal_stages 查詢 Stage 狀態:
-- 查詢全部 Stage 或按名稱過濾
-- 可替換變數:<internal_stage_name> 替換為 Stage 名稱時僅查詢該 Stage;省略 WHERE 則查詢全部
SELECT * FROM hologres.hg_internal_stages
[WHERE stage_name = '<internal_stage_name>'];包含如下欄位:
欄位名 | 含義 |
stage_name | Stage 名稱 |
group_name | Stage 所屬分組 |
ttl_in_seconds | Stage 生命週期(秒) |
create_time | Stage 建立時間 |
create_user | 建立 Stage 的使用者 |
create_application_name | 建立 Stage 的應用程式 |
create_session_id | 建立 Stage 的會話 ID |
last_modified_time | Stage 最後一次更新時間 |
stage_bytes | Stage 儲存大小(Byte) |
file_count | Stage 檔案數 |
查詢 Stage 檔案
可通過系統檢視表 hologres.hg_internal_stage_files 查詢 Stage 檔案:
-- 查詢 Stage 下檔案清單,可按名稱模糊過濾
-- 可替換變數:<internal_stage_name> Stage 名稱;<pattern%> 檔案名稱模糊比對(如 'batch_%')
SELECT * FROM hologres.hg_internal_stage_files
[WHERE stage_name = '<internal_stage_name>']
[AND file_name like '<pattern%>'];包含如下欄位:
欄位名 | 含義 |
stage_name | Stage 名稱 |
file_name | 檔案名稱 |
file_size | 檔案儲存體大小(Byte) |
last_modified_time | 檔案最後一次更新時間 |
is_complete | 檔案是否寫入成功。True 表示寫入成功,False 表示正在寫入或寫入失敗 |
刪除 Stage 檔案
可通過系統函數 hologres.hg_remove_internal_stage_file 刪除 Stage 檔案:
-- 刪除指定檔案
-- 可替換變數:<stage_name> Stage 名稱;<file_name> 要刪除的檔案名稱
SELECT hologres.hg_remove_internal_stage_file ('<stage_name>', '<file_name>');
-- 大量刪除 Stage 檔案
-- 可替換變數:<stage_name> Stage 名稱;<glob_pattern> 檔案名稱通配(如 '*.arrow');<pattern%> WHERE 中的檔案名稱模糊比對
SELECT
stage_name,
file_name,
hologres.hg_remove_internal_stage_file (stage_name, file_name) AS hg_remove_internal_stage_file
FROM
hologres.hg_list_internal_stage_files ('<stage_name>',['<glob_pattern>'])
[WHERE file_name like '<pattern%>'];使用 Stage
用戶端寫入 Stage
命令格式:
-- 將用戶端資料流寫入 Stage 指定檔案
-- 可替換變數:<internal_stage_name> 已建立的 Stage 名稱;<file_name> 寫入的檔案名稱(支援字母、數字、底線、連字號、英文句號,最大 128 字元)
COPY EXTERNAL_FILES(
path = 'internal_stage://<internal_stage_name>/<file_name>'
) FROM STDIN;通過 COPY 命令寫入 Stage 時不支援配置 COPY 文法中的 WITH 參數。通過 path 參數定義 Stage 檔案路徑,支援字母(大小寫敏感)、數字、底線、連字號、英文句號,最大長度 128 字元。
讀取 Stage 寫入內表
命令格式:
-- 從 Stage 讀取 Arrow 檔案並寫入內表
-- 可替換變數:
-- <table_name> 目標內表名
-- <col_name> 列名(可選,指定時與目標表列一一對應)
-- <internal_stage_name> Stage 名稱,可寫多個用逗號分隔以讀取多個 Stage
-- <col_type> 列類型(可選,僅在 AS 子句中指定列類型時使用)
INSERT INTO <table_name> [ ( <col_name> [ , <col_name> ... ] ) ]
SELECT *
FROM EXTERNAL_FILES(
path = 'internal_stage://<internal_stage_name>, internal_stage://<internal_stage_name>',
format = arrow
)
[AS ( <col_name> <col_type>[ , <col_name> <col_type> ... ] )];讀取 Stage 僅支援 Arrow 格式檔案。
使用樣本
通過 Holo-client 寫入 Stage
以下樣本示範如何使用 Holo-client 通過 Stage 進行近即時寫入。
Maven 依賴:
<dependency>
<groupId>com.alibaba.hologres</groupId>
<artifactId>holo-client</artifactId>
<version>2.7.0</version>
</dependency>範例程式碼:
import com.alibaba.hologres.client.HoloClient;
import com.alibaba.hologres.client.HoloConfig;
import com.alibaba.hologres.client.Put;
import com.alibaba.hologres.client.copy.CopyUtil;
import com.alibaba.hologres.client.copy.in.CopyInStageWrapper;
import com.alibaba.hologres.client.copy.in.arrow.RecordArrowWriter;
import com.alibaba.hologres.client.model.OnConflictAction;
import com.alibaba.hologres.client.model.TableSchema;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CopyStageDemo {
public static void main(String[] args) throws Exception {
// 注意:jdbcUrl需使用jdbc:hologres協議
String jdbcUrl = "jdbc:hologres://host:port/db";
String username = "";
String password = "";
/*
CREATE TABLE copy_stage_demo (id INT NOT NULL, name TEXT NOT NULL, address TEXT, PRIMARY KEY(id));
*/
String tableName = "copy_stage_demo";
HoloConfig config = new HoloConfig();
config.setJdbcUrl(jdbcUrl);
config.setUsername(username);
config.setPassword(password);
config.setRegion("local");
// 建立臨時Stage名稱
String stageName = "temp_stage_" + System.currentTimeMillis();
try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
HoloClient client = new HoloClient(config)) {
// 建立內部Stage
String createStageSql =
"call hologres.hg_create_internal_stage('"
+ stageName
+ "', 'default_group', 7200);";
try (java.sql.Statement stmt = conn.createStatement()) {
stmt.execute(createStageSql);
}
// 擷取表結構
TableSchema schema = client.getTableSchema(tableName);
// 定義要寫入的列
List<String> columns = new ArrayList<>();
columns.add("id");
columns.add("name");
columns.add("address");
// 使用RecordArrowWriter和CopyInStageWrapper寫入資料到Stage
try (RecordArrowWriter arrowWriter =
new RecordArrowWriter(
schema,
columns,
8192 // maxBatchSize,每1024行資料群組成一個Arrow RecordBatch
);
CopyInStageWrapper<com.alibaba.hologres.client.model.Record> copyInStage =
new CopyInStageWrapper<>(
config,
stageName,
"data_file", // 檔案名稱首碼
arrowWriter,
64 * 1024 * 1024 // fileSizeLimit,每個檔案大小64 MB
)) {
// 寫入10條資料
for (int i = 0; i < 10; ++i) {
Put put = new Put(schema);
// 和CopyInStageWrapper的columns保持一致
put.setObject("id", i);
put.setObject("name", "name" + i);
put.setObject("address", "address" + i);
copyInStage.putRecord(put.getRecord());
}
// 程式結束之前需要調用close,保證資料完全寫入
// demo使用了try-with-resources,無需手動close
// copyInStage.close();
}
// 產生從Stage寫入目標表的INSERT語句
String insertSql =
CopyUtil.buildInsertTableSelectFromStageSql(
schema,
columns,
Collections.singletonList(stageName),
OnConflictAction.INSERT_OR_UPDATE);
try (java.sql.Statement stmt = conn.createStatement()) {
stmt.execute(insertSql);
}
// 驗證寫入結果
try (java.sql.Statement stmt = conn.createStatement()) {
try (java.sql.ResultSet rs = stmt.executeQuery("select * from " + tableName)) {
while (rs.next()) {
System.out.println(
"id: "
+ rs.getInt(1)
+ ", name: "
+ rs.getString(2)
+ ", address: "
+ rs.getString(3));
}
}
}
} finally {
// 清理臨時Stage,不清理的話也會根據TTL自動清理
try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
java.sql.Statement stmt = conn.createStatement()) {
String dropStageSql = "call hologres.hg_drop_internal_stage('" + stageName + "');";
stmt.execute(dropStageSql);
} catch (Exception e) {
System.err.println("清理Stage時出錯: " + e.getMessage());
}
}
}
}資料類型映射
通過 Stage 近即時匯入時,Arrow 格式與 Hologres 資料類型對應關係如下。使用 Holo-client 進行寫入時,已自動進行資料類型轉換。
Hologres 資料類型 | Arrow 資料類型 |
SMALLINT | SMALLINT |
INT | INT |
BIGINT | BIGINT |
BOOLEAN | UINT8、BIT |
REAL(FLOAT4) | FLOAT4 |
DOUBLE PRECISION(FLOAT8) | FLOAT8 |
DATE | DateDay |
TIMETZ | FixedSizeBinary |
TIME | TimeMicro |
TIMESTAMP WITHOUT TIME ZONE | TimeStampMicro |
TIMESTAMP WITH TIME ZONE | DateMilli |
TEXT | VarChar |
CHAR(n) | — |
VARCHAR(n) | — |
JSON | — |
JSONB | — |
BYTEA | VarBINARY |
roaringbitmap | — |
NUMERIC(m,n) | DECIMAL(m,n) |
ARRAY(支援 INT、BIGINT、FLOAT、BOOLEAN、DOUBLE、STRING) | ARRAY<type> |