AlloyDB から Iceberg データにアクセスする

AlloyDB for PostgreSQL の Iceberg への直接アクセスを使用すると、AlloyDB インスタンスから Cloud Storage の Apache Iceberg テーブル形式で保存されたデータにクエリを実行できます。Iceberg データセットには、Cloud Storage バケット URI または Lakehouse ランタイム カタログを使用してアクセスできます。分析ワークロードを高速化するために、AlloyDB にはスキャン、結合、集計を最適化する組み込みのカラム型エンジンが用意されています。カラム型エンジンと統合することで、Iceberg に直接アクセスして、複雑な抽出、変換、読み込み(ETL)データ パイプラインを構築、管理、維持することなく、データ レイクハウスで高パフォーマンスの分析クエリを実行できます。

標準 SQL コマンドを使用して Iceberg テーブルに対してクエリを実行し、Iceberg データセットを AlloyDB の運用テーブルと結合して、Iceberg テーブルをメモリ内カラム型エンジンに読み込み、クエリ パフォーマンスを高速化できます。

利点

Iceberg への直接アクセスには、次の利点があります。

  • ゼロ ETL レイクハウス アクセス: データを別の分析システムにコピーまたは移動することなく、外部の Iceberg データセットをその場でクエリします。
  • 統合されたトランザクション クエリと分析クエリ: AlloyDB ヒープテーブルに保存されているライブの運用データと、Cloud Storage の Iceberg テーブルに保存されている大量の過去のデータを結合します。
  • 柔軟なカタログ統合: Cloud Storage バケットパスまたは Lakehouse ランタイム カタログを介して Iceberg テーブルのメタデータにアクセスします。
  • カラム型クエリの高速化: Iceberg テーブルをキャッシュに保存して AlloyDB カラム型エンジンメモリに読み込み、1 秒未満の分析処理を実現します。
  • 標準 SQL インターフェース: 使い慣れた PostgreSQL 構文を使用して、Iceberg テーブルのクエリと分析を行います。

Iceberg への直接アクセスの仕組み

Iceberg への直接アクセスでは、PostgreSQL Table Access Method(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 バケットの直接パス(gs://)と Lakehouse ランタイム カタログのパス(bl://)をサポートしています。Lakehouse ランタイム カタログの場合、AlloyDB はエンドユーザー認証情報モードのみをサポートします。認証情報自動販売モードやその他の REST カタログはサポートされていません。
  • リクエスト元による支払いバケット: AlloyDB は、リクエスト元による支払いを使用する Cloud Storage バケットをサポートしていません。
  • 完全な列の入力制約: AlloyDB は、Iceberg テーブルの部分的な列の入力をサポートしていません。テーブルは、カラム型エンジンのメモリまたは SSD スペースに収まる必要があります。
  • 母集団ヒープメモリ: 大規模な Parquet 行グループを含む Iceberg テーブルにデータを入力すると、特に vCPU 数が少ないインスタンスでは、ワーカーあたりの母集団ヒープメモリの上限を超える可能性があります。この問題を解決するには、カラム型エンジンの入力ヒープがいっぱいであるをご覧ください。

始める前に

Iceberg テーブルを作成してクエリを実行する前に、次の操作を完了してください。

  1. Google Cloudで PostgreSQL 18 以降を実行する AlloyDB クラスタを作成します。詳細については、クラスタを作成するをご覧ください。
  2. Cloud Storage で Apache Iceberg テーブルをホストするか、Lakehouse ランタイム カタログに登録します。
    • Cloud Storage パスの場合、バケット ディレクトリ構造は、メタデータ JSON ファイルと version-hint.text を含む data/ サブディレクトリと metadata/ サブディレクトリを含む標準の Apache Iceberg レイアウトに従う必要があります。詳細については、バケットを作成するをご覧ください。
    • レイクハウス ランタイム カタログの場合は、エンドユーザー認証情報モードで Iceberg カタログを作成して登録します。詳細については、Apache Iceberg REST カタログ エンドポイントを設定するをご覧ください。
  3. alloydbsuperuser ロールを持つユーザーのデータベース認証情報を設定します。詳細については、alloydbsuperuser グループのロールをご覧ください。

必要なロール

AlloyDB が Iceberg のデータとメタデータを読み取れるようにするには、AlloyDB クラスタ サービス アカウントに必要な IAM ロールを付与する必要があります。

  • Cloud Storage へのアクセス: Iceberg データとメタデータを含む Cloud 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 コンソールの [クラスタの概要] ページでサービス アカウントを確認できます。

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 バケットの名前。
  • 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 パスからテーブルを作成する

次の例では、Cloud Storage バケットにある Iceberg データセットを基盤とする customer_orders という名前のテーブルを作成します。

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 でテーブルを作成したら、alloydbsuperuser 権限を持つ標準 SQL SELECT ステートメントを使用してクエリを実行できます。必要に応じて、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');

クエリで使用する特定の列のみを入力するには、列名のカンマ区切りのリストを 2 番目の引数として渡します。次に例を示します。

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 バケットへの読み取りアクセス権がありません。

推奨される修正: バケットのクラスタ サービス アカウントに roles/storage.objectViewer ロールを付与します。

Lakehouse ランタイム カタログへのアクセスが拒否されました

原因: AlloyDB クラスタ サービス アカウントに、Lakehouse ランタイム カタログへの読み取りアクセス権がありません。

推奨される修正: Lakehouse ランタイム カタログをホストする Google Cloud プロジェクトのクラスタ サービス アカウントに roles/biglake.viewer ロールを付与します。

カラム型入力が失敗する

原因: 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 行グループの入力に必要なメモリが、ワーカーあたりの入力ヒープの上限を超えています。

推奨される修正: 並列ポピュレーション ワーカーの数を減らして、ポピュレーション プロセスがより大きなヒープを使用できるようにします。テーブルにデータを入力する SQL セッションで、google_columnar_engine_add() 関数を呼び出す前に google_job_scheduler.max_parallel_workers_per_job フラグを 0 に設定します。

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

TABLE_NAME は、AlloyDB の Iceberg テーブルの名前に置き換えます。

次のステップ