Apache Iceberg BigLake テーブルを作成する

BigLake を使用すると、きめ細かなアクセス制御によって Iceberg テーブルにアクセスできます。そのためには、まず Iceberg BigLake テーブルを作成する必要があります。

Iceberg は、ペタバイト規模のデータテーブルをサポートするオープンソースのテーブル形式です。Iceberg はオープンな仕様であるので、オブジェクト ストアに保存されたデータに対して複数のクエリエンジンを実行できます。

BigQuery 管理者は、テーブルのデータ マスキングなど、行レベルと列レベルのアクセス制御を適用できます。テーブルレベルでアクセス制御を設定する方法については、アクセス制御ポリシーを設定するをご覧ください。Dataproc とサーバーレス Spark でテーブルのデータソースとして BigQuery Storage API を使用する場合も、テーブル アクセス ポリシーが適用されます。BigLake テーブルを使用すると、他の BigQuery サービスとも統合できます。利用可能なインテグレーションの完全なリストについては、BigLake テーブルの概要をご覧ください。

Iceberg BigLake テーブルは次の方法で作成できます。

  • BigLake Metastore を使用する(Google Cloud の場合に推奨)BigLake Metastore は、カスタムの Iceberg カタログです。Spark と BigQuery のワークロード間でテーブルの同期が可能なため、Google Cloud では BigLake Metastore を使用することをおすすめします。これを行うには、Apache Spark 用の BigQuery ストアド プロシージャを使用して BigLake Metastore を初期化し、Iceberg BigLake テーブルを作成します。ただし、スキーマの更新では引き続き BigQuery で更新クエリを実行する必要があります。

  • AWS Glue Data Catalog を使用する(AWS の場合に推奨)AWS Glue は、さまざまな AWS サービスに保存されているデータの構造と場所を定義し、自動スキーマ検出や AWS 分析ツールとの統合などの機能を提供する、一元化されたメタデータ リポジトリです。AWS では AWS Glue を使用することをおすすめします。

  • Iceberg JSON メタデータ ファイルを使用する(Azure の場合に推奨)。Iceberg JSON メタデータ ファイルを使用する場合は、テーブルが更新されるたびに最新のメタデータ ファイルを手動で更新する必要があります。Apache Spark 用の BigQuery ストアド プロシージャを使用して、Iceberg メタデータ ファイルを参照する Iceberg BigLake テーブルを作成できます。Google Cloud でこれを回避するには、BigLake Metastore を使用します。AWS の場合は AWS Glue Data Catalog を使用します。

    制限事項の一覧については、制限事項をご覧ください。

始める前に

  • BigQuery Connection, BigQuery Reservation, and BigLake API を有効にします。

    API を有効にする

  • BigQuery で Spark のストアド プロシージャを使用して Iceberg BigLake テーブルを作成する場合は、次の操作を行う必要があります。

    1. Spark 接続を作成します
    2. その接続のアクセス制御を設定します
  • Iceberg BigLake のテーブル メタデータとデータファイルを Cloud Storage に保存するために、Cloud Storage バケットを作成します。メタデータ ファイルにアクセスするには、Cloud Storage バケットに接続する必要があります。方法は次のとおりです。

    1. Cloud リソースの接続を作成します
    2. その接続のアクセスを設定します
  • BigLake Metastore を使用する場合は、Apache Spark 用の適切な Iceberg カスタム カタログをインストールします。使用している Iceberg のバージョンに最適なカスタム カタログ バージョンを選択します。

    1. Iceberg 1.5.0: gs://spark-lib/biglake/biglake-catalog-iceberg1.5.0-0.1.1-with-dependencies.jar
    2. Iceberg 1.2.0: gs://spark-lib/biglake/biglake-catalog-iceberg1.2.0-0.1.1-with-dependencies.jar
    3. Iceberg 0.14.0: gs://spark-lib/biglake/biglake-catalog-iceberg0.14.0-0.1.1-with-dependencies.jar

必要なロール

BigLake API の呼び出し元に BigLake テーブルの作成に必要な権限を付与するには、BigLake API の呼び出し元に、プロジェクトに対する次の IAM ロールを付与するよう管理者に依頼します。

ロールの付与の詳細については、アクセス権の管理をご覧ください。

これらの事前定義ロールには、BigLake テーブルの作成に必要な権限が含まれています。必要とされる正確な権限については、「必要な権限」セクションを開いてご確認ください。

必要な権限

BigLake テーブルを作成するには、次の権限が必要です。

  • bigquery.tables.create
  • bigquery.connections.delegate
  • bigquery.jobs.create

管理者は、カスタムロールや他の事前定義ロールを使用して、これらの権限を BigLake API の呼び出し元に付与することもできます。

また、BigQuery ユーザーがテーブルにクエリを実行できるようにするには、接続に関連付けられたサービス アカウントに BigLake 閲覧者(roles/biglake.viewer)のロールと、そのデータを含む Cloud Storage バケットへのアクセス権が必要です。

BigLake Metastore を使用して Iceberg BigLake テーブルを作成するには、BigLake API の呼び出し元を変更します。Dataproc または Spark サービス アカウントに、そのデータを含む Cloud Storage バケットへのアクセス権を付与する必要があります。

BigLake Metastore を使用してテーブルを作成する

Iceberg BigLake テーブルは、BigLake Metastore を使って作成することをおすすめします。Apache Spark を使用して、これらのテーブルを作成できます。これを簡単に行うには、次の手順で BigQuery の Spark 用ストアド プロシージャを使用します。

  1. [BigQuery] ページに移動します。

    [BigQuery] に移動

  2. [エクスプローラ] ペインで、接続リソースの作成に使用したプロジェクトの接続をクリックします。

  3. Spark 用のストアド プロシージャを作成するには、 [ストアド プロシージャを作成] をクリックします。

  4. クエリエディタで、表示される CREATE PROCEDURE ステートメントを使用して BigLake Metastore を初期化し、Iceberg BigLake テーブルを作成するサンプルコードを変更します。

     # Creates a stored procedure that initializes BLMS and database.
     # Creates a table in the database and populates a few rows of data.
     CREATE OR REPLACE PROCEDURE iceberg_demo.iceberg_setup_3_3 ()
     WITH CONNECTION `PROCEDURE_CONNECTION_PROJECT_ID.PROCEDURE_CONNECTION_REGION.PROCEDURE_CONNECTION_ID`
     OPTIONS(engine="SPARK",
     jar_uris=["gs://spark-lib/biglake/biglake-catalog-iceberg1.2.0-0.1.0-with-dependencies.jar"],
     properties=[
     ("spark.jars.packages","org.apache.iceberg:iceberg-spark-runtime-3.3_2.12:1.2.0"),
     ("spark.sql.catalog.CATALOG", "org.apache.iceberg.spark.SparkCatalog"),
     ("spark.sql.catalog.CATALOG.catalog-impl", "org.apache.iceberg.gcp.biglake.BigLakeCatalog"),
     ("spark.sql.catalog.CATALOG.hms_uri", "HMS_URI"),
     ("spark.sql.catalog.CATALOG.gcp_project", "PROJECT_ID"),
     ("spark.sql.catalog.CATALOG.gcp_location", "LOCATION"),
     ("spark.sql.catalog.CATALOG.blms_catalog", "CATALOG"),
     ("spark.sql.catalog.CATALOG.warehouse", "DATA_WAREHOUSE_URI")
     ]
     )
     LANGUAGE PYTHON AS R'''
     from pyspark.sql import SparkSession
    
     spark = SparkSession \
       .builder \
       .appName("BigLake Iceberg Example") \
       .enableHiveSupport() \
       .getOrCreate()
    
     spark.sql("CREATE NAMESPACE IF NOT EXISTS CATALOG;")
     spark.sql("CREATE DATABASE IF NOT EXISTS CATALOG.CATALOG_DB;")
     spark.sql("DROP TABLE IF EXISTS CATALOG.CATALOG_DB.CATALOG_TABLE;")
    
     /* Create a BigLake Metastore table and a BigQuery Iceberg table. */
     spark.sql("CREATE TABLE IF NOT EXISTS CATALOG.CATALOG_DB.CATALOG_TABLE (id bigint, demo_name string)
               USING iceberg
               TBLPROPERTIES(bq_table='BQ_DATASET.BQ_TABLE', bq_connection='TABLE_CONNECTION_PROJECT_ID.TABLE_CONNECTION_REGION.TABLE_CONNECTION_ID');
               ")
    
     /* Copy a Hive Metastore table to BigLake Metastore. Can be used together with
        TBLPROPERTIES `bq_table` to create a BigQuery Iceberg table. */
     spark.sql("CREATE TABLE CATALOG.CATALOG_DB.CATALOG_TABLE (id bigint, demo_name string)
                USING iceberg
                TBLPROPERTIES(hms_table='HMS_DB.HMS_TABLE');")
     ''';
    

    次のように置き換えます。

    • PROCEDURE_CONNECTION_PROJECT_ID: Spark プロシージャを実行するための接続を含むプロジェクト(例: myproject)。

    • PROCEDURE_CONNECTION_REGION: Spark プロシージャを実行するための接続を含むリージョン(例: us)。

    • PROCEDURE_CONNECTION_ID: 接続 ID(例: myconnection)。

      Google Cloud コンソールで接続の詳細を表示する場合、接続 ID は接続 ID に表示される完全修飾接続 ID の最後のセクションの値です(例: projects/myproject/locations/connection_location/connections/myconnection)。

    • CATALOG: BigLake Metastore 用に作成する Iceberg カタログの名前。

      デフォルト値は iceberg です。

    • HMS_URI: 既存の Hive メタストア テーブルを BigLake Metastore にコピーする場合は、Hive メタストア URI を指定します。

      例: thrift://localhost:9083

    • PROJECT_ID: BigLake Metastore インスタンスを作成するプロジェクト ID。

      Iceberg の BigLake テーブルも、同じプロジェクトで作成されます。

    • LOCATION: BigLake Metastore インスタンスを作成するロケーション。

      BigQuery は、同じロケーションに保存されている BigLake Metastore インスタンスにのみアクセスできます。

    • DATA_WAREHOUSE_URI: Iceberg のメタデータとデータファイルを保存するために作成した Cloud Storage バケットの URI。

      例: gs://mybucket/iceberg-warehouse

    • CATALOG_DB: BigLake Metastore に作成するデータベースの名前。

      このデータベースは、Iceberg BigLake テーブルが格納される BigQuery データセットに相当します。

    • CATALOG_TABLE: BigLake Metastore に作成するテーブルの名前。

      このテーブルは、作成する Iceberg BigLake テーブルに相当します。

    • BQ_DATASET: Iceberg BigLake テーブルを格納する BigQuery データセット。

    • BQ_TABLE: 作成する Iceberg BigLake テーブル。

    • TABLE_CONNECTION_PROJECT_ID: BigLake テーブルを作成するための接続を含むプロジェクト(例: myproject)。

    • TABLE_CONNECTION_REGION: BigLake テーブルを作成するための接続を含むリージョン(例: us)。

    • TABLE_CONNECTION_ID: 接続 ID(例: myconnection)。

      Google Cloud コンソールで接続の詳細を表示する場合、接続 ID は接続 ID に表示される完全修飾接続 ID の最後のセクションの値です(例: projects/myproject/locations/connection_location/connections/myconnection)。

      BigQuery ユーザーがテーブルをクエリできるようにするには、接続に関連付けられたサービス アカウントに roles/biglake.viewer が必要です。

    • HMS_DB: 既存の Hive メタストア テーブルを BigLake Metastore にコピーする場合は、Hive メタストア データベースを指定します。

    • HMS_TABLE: 既存の Hive メタストア テーブルを BigLake Metastore にコピーする場合は、Hive メタストア テーブルを指定します。

    Iceberg カタログ構成の詳細については、Spark カタログをご覧ください。

  5. [実行] をクリックして、ストアド プロシージャを実行します。詳細については、Spark ストアド プロシージャの呼び出しをご覧ください。BigQuery に Iceberg BigLake テーブルが作成されます。

メタデータ ファイルを使用してテーブルを作成する

Iceberg BigLake テーブルは、JSON メタデータ ファイルを使用して作成できます。ただし、BigLake テーブルを最新の状態に保つには、手動で JSON メタデータ ファイルの URI を更新する必要があるため、この方法はおすすめしません。URI が最新の状態でないと、BigQuery のクエリが失敗するか、Iceberg カタログを直接使用するその他のクエリエンジンと異なる結果になる可能性があります。これを回避するには、BigLake Metastore インスタンスを参照して Iceberg BigLake テーブルを作成します。

Iceberg テーブルのメタデータ ファイルは、Spark を使用して Iceberg テーブルを作成したときに指定した Cloud Storage バケットに作成されます。

次のオプションのいずれかを選択します。

SQL

CREATE EXTERNAL TABLE ステートメントを使用します。次の例では、myexternal-table という名前の BigLake テーブルが作成されます。

  CREATE EXTERNAL TABLE myexternal-table
  WITH CONNECTION `myproject.us.myconnection`
  OPTIONS (
         format = 'ICEBERG',
         uris = ["gs://mybucket/mydata/mytable/metadata/iceberg.metadata.json"]
   )

uris 値は、特定のテーブル スナップショットの最新の JSON メタデータ ファイルに置き換えます。

require_partition_filter フラグを設定すると、パーティション フィルタを要求できます。

bq

コマンドライン環境では、@connection デコレータを指定した bq mk --table コマンドを使用して、--external_table_definition パラメータの最後に、使用する接続を指定します。パーティション フィルタの要求を有効にするには、--require_partition_filter を使用します。

bq mk 
--table
--external_table_definition=TABLE_FORMAT=URI@projects/CONNECTION_PROJECT_ID/locations/CONNECTION_REGION/connections/CONNECTION_ID
PROJECT_ID:DATASET.EXTERNAL_TABLE

次のように置き換えます。

  • TABLE_FORMAT: 作成するテーブルの形式。

    この場合は ICEBERG です。

  • URI: 特定のテーブル スナップショットの最新の JSON メタデータ ファイル

    たとえば、gs://mybucket/mydata/mytable/metadata/iceberg.metadata.json のようにします。

    URI は、Amazon S3 や Azure Blob Storage などの外部クラウド ロケーションも参照できます。

    • AWS の例: s3://mybucket/iceberg/metadata/1234.metadata.json
    • Azure の例: azure://mystorageaccount.blob.core.windows.net/mycontainer/iceberg/metadata/1234.metadata.json
  • CONNECTION_PROJECT_ID: BigLake テーブルを作成するための接続を含むプロジェクト(例: myproject)。

  • CONNECTION_REGION: BigLake テーブルを作成するための接続を含むリージョン(例: us)。

  • CONNECTION_ID: テーブル接続 ID(例: myconnection)。

    Google Cloud コンソールで接続の詳細を表示する場合、接続 ID は接続 ID に表示される完全修飾接続 ID の最後のセクションの値です(例: projects/myproject/locations/connection_location/connections/myconnection)。

  • DATASET: 作成したテーブルを格納する BigQuery データセットの名前

    例: mydataset

  • EXTERNAL_TABLE: 作成するテーブルの名前。

    例: mytable

テーブル メタデータの更新

JSON メタデータ ファイルを使用して Iceberg BigLake テーブルを作成する場合は、テーブル定義を最新のテーブル メタデータに更新します。スキーマまたはメタデータ ファイルを更新するには、次のいずれかのオプションを選択します。

bq

  1. テーブル定義ファイルを作成します。

    bq mkdef --source_format=ICEBERG \
    "URI" > TABLE_DEFINITION_FILE
    
  2. --autodetect_schema フラグを指定して bq update コマンドを使用します。

    bq update --autodetect_schema --external_table_definition=TABLE_DEFINITION_FILE
    PROJECT_ID:DATASET.TABLE
    

    次のように置き換えます。

    • URI: 最新の JSON メタデータ ファイルを含む Cloud Storage URI

      例: gs://mybucket/us/iceberg/mytable/metadata/1234.metadata.json

    • TABLE_DEFINITION_FILE: テーブル スキーマを含むファイルの名前

    • PROJECT_ID: 更新するテーブルを含むプロジェクト ID

    • DATASET: 更新するテーブルを含むデータセット

    • TABLE: 更新するテーブル。

API

autodetect_schema プロパティを true に設定して tables.patch メソッドを使用します。

PATCH https://bigquery.googleapis.com/bigquery/v2/projects/PROJECT_ID/datasets/DATASET/tables/TABLE?autodetect_schema=true

次のように置き換えます。

  • PROJECT_ID: 更新するテーブルを含むプロジェクト ID
  • DATASET: 更新するテーブルを含むデータセット
  • TABLE: 更新するテーブル。

リクエストの本文で、次のフィールドの更新後の値を指定します。

{
     "externalDataConfiguration": {
      "sourceFormat": "ICEBERG",
      "sourceUris": [
        "URI"
      ]
    },
    "schema": null
  }'

URI は、最新の Iceberg メタデータ ファイルに置き換えます。例: gs://mybucket/us/iceberg/mytable/metadata/1234.metadata.json

アクセス制御ポリシーを設定する

BigLake テーブルへのアクセスを制御する方法はいくつかあります。

たとえば、データセット mydataset 内のテーブル mytable に対する行アクセスを制限する必要があるとします。

+---------+---------+-------+
| country | product | price |
+---------+---------+-------+
| US      | phone   |   100 |
| JP      | tablet  |   300 |
| UK      | laptop  |   200 |
+---------+---------+-------+

Kim(kim@example.com)用に行レベルのフィルタを作成して、アクセス権を countryUS の行だけに制限できます。

CREATE ROW ACCESS POLICY only_us_filter
ON mydataset.mytable
GRANT TO ('user:kim@example.com')
FILTER USING (country = 'US');

次に、Kim が次のクエリを実行すると:

SELECT * FROM projectid.mydataset.mytable;

出力には、countryUS の行のみが表示されます。

+---------+---------+-------+
| country | product | price |
+---------+---------+-------+
| US      | phone   |   100 |
+---------+---------+-------+

BigLake テーブルにクエリを実行する

詳細については、Iceberg データにクエリを実行するをご覧ください。

データ マッピング

BigQuery は、次の表に示すように Iceberg のデータ型を BigQuery のデータ型に変換します。

Iceberg のデータ型 BigQuery のデータ型
boolean BOOL
int INT64
long INT64
float FLOAT64
double FLOAT64
Decimal(P/S) NUMERIC or BIG_NUMERIC depending on precision
date DATE
time TIME
timestamp DATETIME
timestamptz TIMESTAMP
string STRING
uuid BYTES
fixed(L) BYTES
binary BYTES
list<Type> ARRAY<Type>
struct STRUCT
map<KeyType, ValueType> ARRAY<Struct<key KeyType, value ValueType>>

制限事項

Iceberg BigLake テーブルには、BigLake テーブルの制限があり、次の制限もあります。

  • copy-on-write 構成はサポートされていますが、merge-on-read 構成はサポートされていません。詳しくは、Iceberg の構成をご覧ください。

  • BigQuery では、Bucket を除くすべての Iceberg パーティション変換関数を使用したマニフェスト プルーニングがサポートされています。パーティションをプルーニングする方法については、パーティション分割テーブルに対してクエリを実行するをご覧ください。Iceberg BigLake テーブルを参照するクエリでは、パーティション分割される列に対するリテラルが熟語に含まれている必要があります。

  • Apache Parquet データファイルのみがサポートされています。

  • BigLake Metastore を使用している場合は、次の制限が適用されます。

    • BigLake Metastore は BigQuery Omni リージョンではサポートされていません。
    • テーブルの名前を変更する場合、変更後のテーブルは変更前のテーブルと同じデータベース内に存在する必要があります。変更後のテーブルのデータベースは、明示的に指定する必要があります。
    • Iceberg メタデータ テーブルを検査する場合は、完全修飾されたテーブル名を使用する必要があります。例: prod.db.table.history

費用

オンデマンド(TB 単位)クエリの料金では、BigLake Metastore へのリクエスト 6,250,000 件あたりおよび BigLake Metastore に保存されている 625,000 件ごとに 1 TB の料金が請求されます。オンデマンド クエリの料金は、リージョンによって異なります。リクエストまたはオブジェクトの数が少ない場合は、1 TB の適切な割合が課金されます。

たとえば、BigLake Metastore に 6,250,000 リクエストを行い、312,500 のオブジェクトを保存した場合、BigLake Metastore インスタンスを作成したリージョンのオンデマンド クエリ料金のレートで、1.5 TB に対して課金されます。

パーティション フィルタを要求

Iceberg テーブルのパーティション フィルタを要求するオプションを有効にすると、述語フィルタの使用を要求できます。このオプションが有効になっているときに、各マニフェスト ファイルに対応する WHERE 句を指定せずにテーブルにクエリを実行しようとすると、次のエラーが発生します。

Cannot query over table project_id.dataset.table without a
filter that can be used for partition elimination.

各マニフェスト ファイルには、パーティションの除去に適した述語が少なくとも 1 つ必要です。

Iceberg テーブルの作成時に、次の方法で require_partition_filter を有効にできます。

SQL

CREATE EXTERNAL TABLE ステートメントを使用します。次の例では、パーティション フィルタの要求を有効にして、TABLE という名前の BigLake テーブルを作成します。

  CREATE EXTERNAL TABLE TABLE
  WITH CONNECTION `PROJECT_ID.REGION.CONNECTION_ID`
  OPTIONS (
         format = 'ICEBERG',
         uris = [URI],
         require_partition_filter = true
   )

次のように置き換えます。

  • TABLE: 作成するテーブルの名前。
  • PROJECT_ID: 作成するテーブルを含むプロジェクト ID。
  • REGION: Iceberg テーブルを作成するロケーション
  • CONNECTION_ID: 接続 ID。例: myconnection

  • URI: 最新の JSON メタデータ ファイルを含む Cloud Storage URI。

    たとえば、gs://mybucket/us/iceberg/mytable/metadata/1234.metadata.json のようにします。

    URI は、Amazon S3 や Azure Blob Storage などの外部クラウド ロケーションも参照できます。

    • AWS の例: s3://mybucket/iceberg/metadata/1234.metadata.json
    • Azure の例: azure://mystorageaccount.blob.core.windows.net/mycontainer/iceberg/metadata/1234.metadata.json

bq

@connection デコレータを指定した bq mk --table コマンドを使用して、--external_table_definition パラメータの最後に使用する接続を指定します。--require_partition_filter を使用して、パーティション フィルタの要求を有効にします。次の例では、パーティション フィルタの要求を有効にして、TABLE という名前の BigLake テーブルを作成します。

bq mk \
    --table \
    --external_table_definition=ICEBERG=URI@projects/CONNECTION_PROJECT_ID/locations/CONNECTION_REGION/connections/CONNECTION_ID \
    PROJECT_ID:DATASET.EXTERNAL_TABLE \
    --require_partition_filter

次のように置き換えます。

  • URI: 特定のテーブル スナップショットの最新の JSON メタデータ ファイル

    たとえば、gs://mybucket/mydata/mytable/metadata/iceberg.metadata.json のようにします。

    URI は、Amazon S3 や Azure Blob Storage などの外部クラウド ロケーションも参照できます。

    • AWS の例: s3://mybucket/iceberg/metadata/1234.metadata.json
    • Azure の例: azure://mystorageaccount.blob.core.windows.net/mycontainer/iceberg/metadata/1234.metadata.json
  • CONNECTION_PROJECT_ID: BigLake テーブルを作成するための接続を含むプロジェクト(例: myproject)。

  • CONNECTION_REGION: BigLake テーブルを作成するための接続を含むリージョン(例: us)。

  • CONNECTION_ID: 接続 ID。例: myconnection

    Google Cloud コンソールで接続の詳細を表示する場合、接続 ID は接続 ID に表示される完全修飾接続 ID の最後のセクションの値です(例: projects/myproject/locations/connection_location/connections/myconnection)。

  • DATASET: 更新するテーブルを含む BigQuery データセットの

    名前。例: mydataset

  • EXTERNAL_TABLE: 作成するテーブルの名前

    例: mytable

Iceberg テーブルを更新して、パーティション フィルタの要求を有効にすることもできます。

パーティション分割テーブルを作成するときに、パーティション フィルタを要求するオプションを有効にしない場合でも、テーブルを更新してオプションを追加できます。

bq

bq update コマンドを使用し、--require_partition_filter フラグを指定します。

次に例を示します。

デフォルト プロジェクトで mydatasetmypartitionedtable を更新するには、次のように入力します。

bq update --require_partition_filter PROJECT_ID:DATASET.TABLE

次のステップ