從 AlloyDB 存取 Iceberg 資料

AlloyDB for PostgreSQL 的直接 Iceberg 存取功能,可讓您從 AlloyDB 執行個體,查詢 Cloud Storage 中以 Apache Iceberg 資料表格式儲存的資料。您可以使用 Cloud Storage bucket URI 或 Lakehouse 執行階段目錄存取 Iceberg 資料集。為加快分析工作負載,AlloyDB 提供內建的資料欄引擎,可最佳化掃描、彙整和匯總作業。直接存取 Iceberg 功能與資料欄引擎整合,可讓您在資料湖倉執行高效能分析查詢,不必建構、管理或維護複雜的擷取、轉換和載入 (ETL) 資料管道。

您可以使用標準 SQL 指令查詢 Iceberg 資料表、將 Iceberg 資料集與 AlloyDB 中的作業資料表彙整,以及將 Iceberg 資料表填入記憶體內資料欄引擎,加快查詢速度。

優點

直接存取 Iceberg 有下列好處:

  • 零 ETL Lakehouse 存取:直接查詢外部 Iceberg 資料集,不必將資料複製或移至獨立的分析系統。
  • 整合交易和分析查詢:將儲存在 AlloyDB 堆積資料表中的即時營運資料,與儲存在 Cloud Storage Iceberg 資料表中的大量歷來資料彙整。
  • 彈性的目錄整合:透過 Cloud Storage bucket 路徑或 Lakehouse 執行階段目錄,存取 Iceberg 資料表中繼資料。
  • 資料欄查詢加速:將 Iceberg 資料表快取並填入 AlloyDB 資料欄引擎記憶體,在 1 秒內完成分析處理。
  • 標準 SQL 介面:使用熟悉的 PostgreSQL 語法查詢及分析 Iceberg 資料表。

直接存取 Iceberg 的運作方式

直接存取 Iceberg 時,會使用 PostgreSQL 資料表存取方法 (TAM) 介面 (USING iceberg),並與 AlloyDB 資料欄引擎規劃工具和執行架構整合。

查詢 Iceberg 資料表時,AlloyDB 會以下列其中一種模式運作:

  • 直接掃描 (用於串流讀取):AlloyDB 直接從 Cloud Storage 讀取最新的中繼資料和資料檔案。資料欄引擎會以串流方式處理資料。
  • 資料欄引擎加速 (用於記憶體內快取讀取):使用 google_columnar_engine_add() 函式將 Iceberg 資料表填入 AlloyDB 資料欄引擎時,資料表會載入記憶體中的資料欄儲存庫。後續查詢會從資料欄引擎記憶體讀取,盡可能提高查詢處理量並縮短延遲時間。

快照提供和快取重新整理

AlloyDB 查詢的 Iceberg 資料表快照取決於讀取模式:

  • 直接掃描:AlloyDB 會對最新的 Iceberg 快照執行查詢。查詢開始時,AlloyDB 會判斷最新可用的 Iceberg 資料表快照,並從該快照讀取資料,即使在 REPEATABLE READ 或 SERIALIZABLE 交易中也是如此。AlloyDB 不支援跨交易的快照固定和時間點查詢。

    舉例來說,使用直接掃描查詢資料表時,交易中的每個陳述式都會從最新可用的快照讀取:

    BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    SELECT * FROM customer_orders;
    -- If an external process commits a new Iceberg snapshot:
    SELECT * FROM customer_orders; -- Returns results from the new snapshot.
    COMMIT;
    
  • 資料欄引擎加速:AlloyDB 會在資料欄引擎中填入的快照執行查詢。如果 AlloyDB 在填入資料後,將新資料寫入 Cloud Storage 中的基礎 Iceberg 資料表,查詢可能會傳回過時資料。如要在基礎資料表上執行 DML 作業後取得最新資料,請使用 google_columnar_engine_refresh() 函式重新整理快取。

支援的資料類型

在 AlloyDB 定義 Iceberg 資料表時,DDL 陳述式中的資料欄名稱和資料類型,必須與基礎 Iceberg 結構定義中的類型相符。

直接存取 Iceberg 支援下列 Apache Iceberg 資料類型和對應的 AlloyDB 類型:

Apache Iceberg 資料類型 AlloyDB 資料類型 說明
boolean BOOLEAN 向量化轉換為位元組封裝格式
int INT/INTEGER 32 位元有正負號整數
long BIGINT 64 位元帶正負號整數
float REAL/FLOAT4 32 位元單精度浮點
double DOUBLE PRECISION/FLOAT8 64 位元雙精度浮點數
decimal(P, S) NUMERIC(P, S)/DECIMAL(P, S) 精確度為 P 且小數位數為 S 的定點數值
string TEXT/VARCHAR UTF-8 字串值
date DATE 日曆日期 (年、月、日)
timestamp TIMESTAMP 不含時區的時間戳記
timestamptz TIMESTAMPTZ 包含時區的時間戳記

限制

直接存取 Iceberg 有下列限制:

  • PostgreSQL 版本可用性:AlloyDB 支援在 PostgreSQL 18 以上版本直接存取 Iceberg。
  • 使用者授權:只有具備 alloydbsuperuser 角色,才能建立 Iceberg 資料表。建立資料表後,您可以將 SELECT 權限授予其他使用者,以便查詢 Iceberg 資料表。
  • 唯讀作業:AlloyDB 僅支援對 Iceberg 資料表執行 SELECT 查詢 (DQL)。不支援寫入作業 (INSERT、UPDATE、DELETE、TRUNCATE)。
  • Apache Iceberg 規格版本:AlloyDB 不支援 Iceberg v2 刪除檔案 (位置和等值刪除) 或 Iceberg v3 刪除向量。
  • 支援的檔案格式:直接存取 Iceberg 支援 Parquet 資料檔案,以及 JSON 和 Avro 中繼資料檔案。不支援 ORC 資料檔案。
  • 快照版本管理:直接掃描查詢會在最新的 Iceberg 資料表快照執行,而資料欄加速查詢則會在填入的快照執行。AlloyDB 不支援時間點查詢。
  • 結構定義演變:AlloyDB 不支援對 Iceberg 資料表執行 ALTER TABLE 作業。基礎 Iceberg 資料表不得經過結構定義遷移。
  • 中繼資料目錄支援:直接存取 Iceberg 時,支援直接 Cloud Storage bucket 路徑 (gs://) 和 Lakehouse 執行階段目錄路徑 (bl://)。針對 Lakehouse 執行階段目錄,AlloyDB 僅支援使用者憑證模式。不支援憑證販售模式或其他 REST 目錄。
  • 要求者付費 bucket:AlloyDB 不支援使用要求者付費的 Cloud Storage bucket。
  • 完整填入限制:AlloyDB 不支援部分填入 Iceberg 資料表的資料欄。資料表必須能放入資料欄引擎記憶體或 SSD 空間。
  • 母體堆積記憶體:填入含有大型 Parquet 資料列群組的 Iceberg 資料表時,可能會超過每個 worker 的母體堆積記憶體限制,尤其是在 vCPU 數量較少的執行個體上。如要解決這個問題,請參閱「資料欄引擎母體堆積已滿」。

事前準備

建立及查詢 Iceberg 資料表前,請務必完成下列事項:

  1. 在 Google Cloud上建立執行 PostgreSQL 18 以上版本的 AlloyDB 叢集。詳情請參閱「建立叢集」。
  2. 在 Cloud Storage 中託管 Apache Iceberg 資料表,或在 Lakehouse 執行階段目錄中註冊:
    • 如果是 Cloud Storage 路徑,bucket 目錄結構必須遵循標準 Apache Iceberg 版面配置,其中包含 data/ 和 metadata/ 子目錄,包括中繼資料 JSON 檔案和 version-hint.text。詳情請參閱「建立 bucket」。
    • 如果是 Lakehouse 執行階段目錄,請在使用者憑證模式下建立及註冊 Iceberg 目錄。詳情請參閱「設定 Apache Iceberg REST 目錄端點」。
  3. 為具備 alloydbsuperuser 角色的使用者設定資料庫憑證。詳情請參閱「alloydbsuperuser 群組角色」。

必要的角色

如要讓 AlloyDB 讀取 Iceberg 資料和中繼資料,您必須將必要的 IAM 角色授予 AlloyDB 叢集服務帳戶:

  • Cloud Storage 存取權:針對含有 Iceberg 資料和中繼資料的 Cloud Storage bucket,授予 Storage 物件檢視者 (roles/storage.objectViewer) 角色。
  • BigLake 存取權 (如果使用 Lakehouse 執行階段目錄):在託管 BigLake 目錄的專案中,授予 BigLake 檢視者 (roles/biglake.viewer) 角色。

如要找出叢集服務帳戶,請執行 gcloud beta alloydb clusters describe 指令:

gcloud beta alloydb clusters describe CLUSTER_ID --region=REGION_ID

更改下列內容:

  • CLUSTER_ID:AlloyDB 叢集 ID。
  • REGION_ID:AlloyDB 叢集的位置。例如,us-east1。如需完整的區域清單,請參閱「AlloyDB 位置」。

輸出內容包含 serviceAccountEmail 欄位,也就是這個叢集的服務帳戶。在 Google Cloud 控制台的「Cluster overview」(叢集總覽) 頁面中,可以找到服務帳戶。

如要使用 gcloud CLI 授予 Storage 物件檢視者角色,請執行:

gcloud storage buckets add-iam-policy-binding \
    gs://BUCKET_NAME \
    --member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
    --role="roles/storage.objectViewer"

如果您使用 Lakehouse 執行階段目錄,請授予 BigLake 檢視者角色:

gcloud projects add-iam-policy-binding LAKEHOUSE_PROJECT_ID \
    --member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
    --role="roles/biglake.viewer"

更改下列內容:

  • BUCKET_NAME:Cloud Storage bucket 的名稱。
  • LAKEHOUSE_PROJECT_ID:託管 Lakehouse 執行階段目錄的 Google Cloud 專案 ID。
  • SERVICE_ACCOUNT_EMAIL:您在 serviceAccountEmail 欄位中找到的叢集服務帳戶電子郵件。

設定資料庫旗標

如要啟用資料欄引擎和直接存取 Iceberg,您可以在 AlloyDB 執行個體設定資料庫旗標。在執行個體上設定下列資料庫旗標:

資料庫旗標 值 說明
google_columnar_engine.enabled on 啟用 AlloyDB 資料欄引擎。
google_columnar_engine.enable_iceberg_reads on 啟用直接存取 Iceberg 的功能。您必須重新啟動執行個體,設定才會生效。
google_columnar_engine.memory_size_in_mb SIZE_IN_MB (選用) 為資料欄引擎分配記憶體。如果打算在記憶體中填入 Iceberg 資料表,建議使用這個選項。

如要使用 gcloud CLI 設定這些旗標,請執行 gcloud alloydb instances update 指令:

gcloud alloydb instances update INSTANCE_ID \
    --cluster=CLUSTER_ID \
    --region=REGION_ID \
    --database-flags=google_columnar_engine.enabled=on,google_columnar_engine.enable_iceberg_reads=on

更改下列內容:

  • INSTANCE_ID:AlloyDB 執行個體的 ID。
  • CLUSTER_ID:AlloyDB 叢集的 ID。
  • REGION_ID:AlloyDB 叢集的區域 ID。

在 AlloyDB 建立 Iceberg 資料表

如要在 AlloyDB 中公開 Apache Iceberg 資料集,請以具備 alloydbsuperuser 權限的使用者身分連線。接著,使用 USING iceberg 資料表存取方法建立資料表。

CREATE TABLE TABLE_NAME (
    COLUMN_NAME DATA_TYPE [, ...]
)
USING iceberg
WITH (
    uri = 'LOCATION_URI'
);

更改下列內容:

  • TABLE_NAME:要在 AlloyDB 建立的資料表名稱。
  • COLUMN_NAME 和 DATA_TYPE:欄定義。資料欄名稱和類型必須與基礎 Iceberg 資料表的結構定義相符。
  • LOCATION_URI:Iceberg 資料表中繼資料的位置。請指定下列其中一種格式:
    • 直接 Cloud Storage 路徑: gs://BUCKET_NAME/PATH_TO_ICEBERG_TABLE
    • Lakehouse 執行階段目錄 URI: bl://projects/PROJECT_ID/catalogs/CATALOG_NAME/databases/DATABASE_NAME/tables/TABLE_NAME

範例

下列範例說明如何在 AlloyDB 中建立 Iceberg 資料表。

從 Cloud Storage 路徑建立資料表

下列範例會建立名為 customer_orders 的資料表,並以 Cloud Storage bucket 中的 Iceberg 資料集為基礎:

CREATE TABLE customer_orders (
    order_id BIGINT,
    customer_id INT,
    order_status TEXT,
    total_amount DOUBLE PRECISION,
    order_date DATE,
    is_completed BOOLEAN
)
USING iceberg
WITH (
    uri = 'gs://my-iceberg-analytics-bucket/datasets/sales/customer_orders'
);

從 Lakehouse 執行階段目錄建立資料表

下列範例會建立資料表,並參照 Lakehouse 執行階段目錄管理的 Iceberg 資料表:

CREATE TABLE customer_orders (
    order_id BIGINT,
    customer_id INT,
    order_status TEXT,
    total_amount DOUBLE PRECISION,
    order_date DATE,
    is_completed BOOLEAN
)
USING iceberg
WITH (
    uri = 'bl://projects/my-analytics-project/catalogs/sales_catalog/databases/retail_db/tables/customer_orders'
);

查詢 Iceberg 資料

在 AlloyDB 建立資料表後,您可以使用標準 SQL SELECT 陳述式和 alloydbsuperuser 權限查詢資料表。您也可以選擇使用 GRANT 陳述式,將讀取的權限授予沒有 alloydbsuperuser 權限的使用者。例如:GRANT SELECT ON customer_orders TO normal_user。

查詢資料

以下範例說明如何執行查詢:

SELECT
    customer_id,
    COUNT(order_id) AS total_orders,
    SUM(total_amount) AS total_spent
FROM customer_orders
WHERE is_completed = true
  AND order_date >= '2026-01-01'
GROUP BY customer_id
ORDER BY total_spent DESC
LIMIT 10;

查詢聯合 Iceberg 資料和作業資料

您可以將 AlloyDB 中的即時營運資料,與 Iceberg 中的歷來資料合併:

SELECT
    c.customer_name,
    c.account_tier,
    COUNT(o.order_id) AS total_orders,
    SUM(o.total_amount) AS historical_spend
FROM customer_orders o
JOIN customers c ON o.customer_id = c.customer_id
WHERE o.is_completed = true
GROUP BY c.customer_name, c.account_tier
ORDER BY historical_spend DESC;

將資料匯入本機資料表

如要在本機 AlloyDB 儲存空間中,建立獨立且可寫入的 Iceberg 資料副本,請執行 CREATE TABLE ... AS SELECT,如以下範例所示:

CREATE TABLE local_customer_orders AS
SELECT * FROM customer_orders
WHERE order_date >= '2026-01-01';

使用資料欄引擎加快查詢速度

如果分析工作負載需要超低延遲時間,您可以直接將 Iceberg 資料表填入 AlloyDB 資料欄引擎記憶體。

將 Iceberg 資料表填入資料欄儲存庫

如要將 Iceberg 資料表的所有資料欄填入 AlloyDB 資料欄引擎,請使用 google_columnar_engine_add() 函式。例如:

SELECT google_columnar_engine_add('customer_orders');

如要僅填入查詢使用的特定資料欄,請傳遞以半形逗號分隔的資料欄名稱清單,做為第二個引數。例如:

SELECT google_columnar_engine_add('customer_orders', 'customer_id,order_status');

詳情請參閱「使用 SQL 函式新增資料欄」。

重新整理填入的資料

如果您將新的快照寫入基礎 Iceberg 資料集,請重新整理資料表,將最新資料重新載入資料欄引擎,讓查詢傳回最新結果:

SELECT google_columnar_engine_refresh('customer_orders');

從資料欄儲存庫中移除資料表

如要從資料欄儲存庫中移除 Iceberg 資料表,並還原為直接掃描:

SELECT google_columnar_engine_drop('customer_orders');

監控及驗證查詢執行

您可以監控 AlloyDB 如何對 Iceberg 資料表執行查詢,並確認查詢是否使用記憶體內資料欄引擎。使用系統檢視表查看快取填入狀態,並使用 EXPLAIN 檢查查詢執行計畫。

驗證資料欄快取狀態

如要確認 Iceberg 資料表是否已填入資料欄引擎,請查詢 g_columnar_relations 系統檢視表:

SELECT relation_name, status
FROM g_columnar_relations
WHERE relation_name = 'customer_orders';

如果 status 值為 USABLE,表示資料表已快取至資料欄引擎記憶體。

使用 EXPLAIN 檢查查詢執行計畫

如要確認查詢是否使用資料欄引擎,請使用 EXPLAIN 陳述式:

EXPLAIN (ANALYZE, COSTS OFF)
SELECT SUM(total_amount)
FROM customer_orders
WHERE is_completed = true;

輸出內容會透過資料表上的 Custom Scan (ColumnarScan) 節點,指出資料欄執行作業:

Custom Scan (ColumnarScan) on customer_orders
  Filter: (is_completed = true)

疑難排解

本節說明如何在 AlloyDB 設定及查詢 Iceberg 資料表,以及如何解決常見問題。

google_columnar_engine.enable_iceberg_reads 旗標已停用

原因:直接存取 Iceberg 的資料庫旗標已停用。

建議修正方式:在執行個體中設定資料庫旗標 google_columnar_engine.enabled=on 和 google_columnar_engine.enable_iceberg_reads=on,然後重新啟動執行個體。

權限遭拒,無法存取 Cloud Storage

原因:AlloyDB 叢集服務帳戶缺少 Cloud Storage bucket 的讀取權限。

建議修正方式:將 bucket 的 roles/storage.objectViewer 角色授予叢集服務帳戶。

權限遭拒,無法存取 Lakehouse 執行階段目錄

原因:AlloyDB 叢集服務帳戶缺少 Lakehouse 執行階段目錄的讀取權限。

建議修正方式:將 roles/biglake.viewer 角色授予託管 Lakehouse 執行階段目錄的 Google Cloud 專案中的叢集服務帳戶。

資料欄填入失敗

原因:Iceberg 資料表大小超過資料欄引擎的可用記憶體和 SSD 空間。

建議修正方式:使用執行個體的 google_columnar_engine.memory_size_in_mb 旗標,增加分配給資料欄引擎的記憶體配置,或使用 google_columnar_engine.storage_cache_size 旗標,增加資料欄引擎儲存空間快取大小。詳情請參閱「設定資料欄引擎的儲存空間快取」。

資料欄引擎填入堆積已滿

錯誤訊息:

ERROR: Columnar engine population heap is full during population. Set
google_columnar_engine.population_heap_size_in_mb to a bigger value.

原因:填入大型 Parquet 資料列群組所需的記憶體,超過每個 worker 的填入堆積限制。

建議修正方式:減少平行母體工作站數量,讓母體程序能使用較大的堆積。在填入資料表的 SQL 工作階段中,請先將 google_job_scheduler.max_parallel_workers_per_job 旗標設為 0,再呼叫 google_columnar_engine_add() 函式:

SET google_job_scheduler.max_parallel_workers_per_job = 0;
SELECT google_columnar_engine_add('TABLE_NAME');

將 TABLE_NAME 替換為 AlloyDB 中的 Iceberg 資料表名稱。

後續步驟