メインコンテンツまでスキップ
に最終更新

Iceberg Catalog

Doris は、さまざまなメタデータサービスを介した Iceberg テーブルのデータへのアクセスをサポートします。データの読み取りに加え、INSERT、INSERT OVERWRITE、UPDATE、DELETE、MERGE INTO による Iceberg テーブルへの書き込みもサポートします。

Apache Doris と Apache Iceberg のクイックスタート。

ヒント

Hive Catalog を使い、Hive Metastore をメタデータサービスとして Iceberg テーブルにアクセスできます。ただし、互換性の問題を避けるため、Iceberg Catalog を直接使用することを推奨します。

適用シナリオ​

シナリオ説明
クエリの高速化Doris の分散コンピューティングエンジンから Iceberg データに直接アクセスし、クエリを高速化します。
データ統合Iceberg データを読み取って Doris の内部テーブルに書き込むか、Doris のコンピューティングエンジンで ZeroETL 操作を実行します。
データの書き戻しDoris がサポートする任意のデータソースのデータを処理し、Iceberg テーブルのストレージに書き戻します。

Catalog の設定​

構文​

CREATE CATALOG [IF NOT EXISTS] catalog_name PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = '<iceberg_catalog_type>',
'warehouse' = '<warehouse>', --optional
{MetaStoreProperties},
{StorageProperties},
{IcebergProperties},
{CommonProperties}
);
  • <iceberg_catalog_type>

    Iceberg Catalog の種類です。次の値をサポートします。

    • hms:Hive Metastore をメタデータサービスとして使用します。

    • rest:Iceberg Rest Catalog インターフェースと互換性のあるメタデータサービスを使用します。

    • hadoop:ファイルシステムに保存されたメタデータに直接アクセスします。

    • glue:AWS Glue をメタデータサービスとして使用します。

    • dlf:Alibaba Cloud DLF をメタデータサービスとして使用します。

    • jdbc:Iceberg JDBC Catalog をメタデータサービスとして使用します。

    • s3tables:AWS S3 Tables Catalog を使用して S3 Table Bucket にアクセスします。

  • <warehouse>

    Iceberg の warehouse パスです。<iceberg_catalog_type> が hadoop の場合は必須です。

    warehouse パスには、Database パスの一つ上の階層を指定します。たとえば、テーブルのパスが s3://bucket/path/to/db1/table1 なら、warehouse は s3://bucket/path/to/ です。

  • {MetaStoreProperties}

    MetaStoreProperties には、Metastore メタデータサービスへの接続情報と認証情報を指定します。[サポートされるメタデータサービス]のセクションを参照してください。

  • {StorageProperties}

    StorageProperties には、ストレージシステムへの接続情報と認証情報を指定します。[サポートされるストレージシステム]のセクションを参照してください。

  • {IcebergProperties}

    IcebergProperties には、Iceberg Catalog 固有のパラメータを指定します。

    • list-all-tables

      Hive Metastore をメタデータサービスとする Iceberg Catalog に適用されます。デフォルトは true です。デフォルトでは、SHOW TABLES は現在のデータベースにあるすべての種類のテーブルを一覧表示します。Hive Metastore には Iceberg 以外のテーブルも保存されている場合があります。この方法が最も高性能です。

      false にすると、Doris は各テーブルの種類を一つずつ確認し、Iceberg テーブルだけを返します。テーブルが多い場合、このモードの性能は低下します。

    • iceberg.rest.view-enabled

      バージョン 4.0.6 以降でサポートされます。

      Iceberg REST Catalog にのみ適用されます。listViews、loadView、viewExists、dropView など、View 関連の操作を有効にするかどうかを指定します。デフォルトは true です。

      Iceberg REST Catalog の実装によっては、Table API は公開されていても View API が利用できないか、エラーを返す場合があります。Doris は SHOW TABLES の実行時に ViewCatalog.listViews() を呼び出してテーブル一覧から View を除外するため、そのような REST サービスでは SHOW TABLES やテーブルメタデータのデータロードが失敗することがあります。

      この場合は false に設定します。Doris がすべての View 関連操作をスキップし、SHOW TABLES などのメタデータ操作を正常に実行できます。

  • {CommonProperties}

    CommonProperties には共通プロパティを指定します。詳細は Catalog の概要を参照してください。

メタデータキャッシュ​

外部データソースへのアクセス性能を高めるため、Apache Doris は Iceberg メタデータをキャッシュします。メタデータには、テーブル構造(Schema)、テーブルオブジェクト、スナップショット、View オブジェクト、マニフェストの詳細が含まれます。

ヒント

Doris 4.1.x より前のバージョンでは、メタデータキャッシュは主に FE の設定項目によって全体的に制御されます。詳細はメタデータキャッシュを参照してください。 Doris 4.1.x 以降では、Iceberg Catalog の外部メタデータキャッシュは統一された meta.cache.* キーで設定します。

キャッシュプロパティの設定(4.1.x 以降)​

各エンジンのキャッシュエントリには、統一された設定キー形式 meta.cache.<engine>.<entry>.{enable,ttl-second,capacity,max-weight} を使用します。メモリ制限は推定器に対応したエントリにのみ適用されます。外部メタデータキャッシュのメモリ管理を参照してください。

プロパティ例意味
enabletrue/falseこのキャッシュモジュールを有効にするかどうか。
ttl-second600, 0, -10 はキャッシュを無効化します(即時に反映され、最新データの確認に利用可能)。-1 は無期限、その他の正の整数はアクセス時刻を基準にした TTL の秒数です。
capacity10000エントリ数によるキャッシュの上限です。max-weight が有効な場合は、同時に適用される件数制限にはなりません。ただし、0 にするとキャッシュは無効になります。
max-weight1GBDoris 4.1.4 以降でサポートされます。保持メモリの推定値に対する省略可能な上限です。Iceberg の table、snapshot、manifest が対応し、0 はそのエントリを無効にします。

有効になる条件: モジュールキャッシュは、enable=true、ttl-second != 0、capacity > 0 で、かつ max-weight が未指定または 0 以外の場合に有効になります。

キャッシュモジュール​

Iceberg Catalog には次のキャッシュモジュールがあります。

モジュール(<entry>)プロパティキーのプレフィックスキャッシュ内容と影響
schemameta.cache.iceberg.schema.テーブル構造をキャッシュします。影響:テーブルのカラム情報が見えるまでの時間。無効にすると、クエリごとに最新の Schema を取得します。
tablemeta.cache.iceberg.table.Iceberg テーブルのメタデータオブジェクトをキャッシュします。影響:Catalog/Metastore との通信回数を減らします。
snapshotmeta.cache.iceberg.snapshot.スナップショットメタデータと保持中のテーブル世代をキャッシュします。影響:スナップショットとパーティション投影の繰り返し読み込みを減らします。このエントリは max-weight に対応します。
viewmeta.cache.iceberg.view.Iceberg View のメタデータオブジェクトをキャッシュします。
manifestmeta.cache.iceberg.manifest.マニフェストの詳細をキャッシュします。影響:マニフェストへの繰り返しアクセスの負荷を減らします。このモジュールはデフォルトで無効のため、手動で有効にする必要があります。

従来のパラメータの対応関係と変換​

バージョン 4.1.x 以降では統一キーを推奨します。従来の Catalog プロパティと 4.1.x 以降の統一キーの対応関係は次のとおりです。

従来のプロパティキー4.1.x 以降の統一キー説明
schema.cache.ttl-secondmeta.cache.iceberg.schema.ttl-secondテーブル構造キャッシュの有効期限

ベストプラクティス​

  • 最新データへのリアルタイムアクセス:Iceberg テーブルの最新スナップショットやスキーマ変更を各クエリで確認するには、schema または table の ttl-second を 0 に設定します。
    -- Disable table object cache to detect snapshot changes
    ALTER CATALOG iceberg_ctl SET PROPERTIES ("meta.cache.iceberg.table.ttl-second" = "0");
  • 性能の最適化:
    • マニフェストキャッシュを有効にすると、大規模テーブルのクエリ計画を大幅に高速化できます。
      ALTER CATALOG iceberg_ctl SET PROPERTIES (
      "meta.cache.iceberg.manifest.enable" = "true",
      "meta.cache.iceberg.manifest.ttl-second" = "600"
      );
    • Doris 4.1.4 以降では、Catalog プロパティの変更が成功すると Catalog の実行コンテキストがリセットされ、その Catalog を経由するすべてのメタデータキャッシュエンジンで初期化済みのエントリが消去されます。次回アクセス時に新しいコンテキストと設定で再構築されます。実行中のクエリには影響しません。

監視​

information_schema.catalog_meta_cache_statistics システムテーブルでキャッシュのメトリクスを確認できます。

SELECT catalog_name, engine_name, entry_name,
effective_enabled, ttl_second, capacity,
estimated_size, hit_rate, load_failure_count, last_error
FROM information_schema.catalog_meta_cache_statistics
WHERE catalog_name = 'iceberg_ctl' AND engine_name = 'iceberg'
ORDER BY entry_name;

このシステムテーブルの詳細は catalog_meta_cache_statistics を参照してください。

サポートされる Iceberg のバージョン​

Doris のバージョンIceberg SDK のバージョン
2.11.6.1
3.01.6.1
3.11.9.1
4.01.9.1
4.1.4 / 4.1.4.11.10.1
4.1.5+1.11.0

メタデータと読み取りのエラー(4.1.5 以降)​

  • DESCRIBE、SHOW COLUMNS、SHOW CREATE TABLE は、現在の Iceberg スキーマの必須/任意の宣言を保持します。スキャンはスキーマ進化によって欠けたフィールドにも対応します。表示される NOT NULL 宣言は、過去のすべてのファイルにそのフィールドが存在することを保証しません。
  • 型を対応付けられない過去のパーティション仕様は、通常の読み取りと行単位の DML に異なる影響を与えることがあります。DELETE または UPDATE では、Cannot produce Iceberg row IDs with unsupported partition types in spec ... により Iceberg Row ID の構築に失敗する場合があります。行単位の変更を行う前に、テーブル形式に対応したライターで過去のデータファイルを書き直してください。
  • コミット済みスナップショットが参照するデータファイルまたは削除ファイルが存在しない場合、ignore_not_found_file_in_external_table=true でもクエリは失敗します。欠けているオブジェクトを復元するか、ファイルがそろっている有効なスナップショットを選択してください。
  • schema.name-mapping.default には、有効な Iceberg Name Mapping の JSON 配列を指定する必要があります。値が無効な場合、現在のカラム名にフォールバックして NULL を返すのではなく、データスキャンが失敗します。Spark などのライターでプロパティを修正または削除してから、Doris でテーブルを更新してください。メタデータのシステムテーブルに対するクエリでは、このデータスキャンの検証は行われません。

サポートされる Iceberg 形式​

  • Iceberg V1/V2 形式をサポートします。
  • Position Delete と Equality Delete の読み取りをサポートします。
  • Deletion Vector の読み取りをサポートします(4.1.0 以降)。

サポートされるメタデータサービス​

注:Doris のバージョンによって、サポートされるサービスの種類とパラメータは多少異なります。[例]のセクションを参照してください。

Iceberg Catalog の機能サポート一覧​

メタデータサービステーブルのクエリView のクエリDDL 操作データの書き戻しシステムテーブル(3.1 以降でサポート)
Hive MetaStore✅✅✅✅✅
AWS Glue✅✅❌❌✅
Aliyun DLF✅✅❌❌❌
Iceberg Rest Catalog✅✅サービスプロバイダーによるサービスプロバイダーによるサービスプロバイダーによる
FileSystem✅✅✅✅✅

サポートされるストレージシステム​

注:Doris のバージョンによって、サポートされるサービスの種類とパラメータは多少異なります。[例]のセクションを参照してください。

サポートされるデータ形式​

バージョン 4.1.4 以降では、ファイル形式をデータファイル(split)ごとに判定するため、Parquet と ORC の両方のデータファイルを含む一つの Iceberg テーブルも正常にクエリできます。テーブルレベルの write.format.default プロパティが設定されていない場合、データファイルを調べて推測するのではなく、デフォルトで parquet を使用します。

バージョン 4.1.4 以降では、Iceberg の identity パーティションメタデータが各 split に渡され、パスのパーティションキーにはすべてのパーティション仕様に共通する identity カラムのみが含まれます。そのため、パーティション進化を経たテーブルでも、パーティションカラムの値が正しく返されます。

カラム型のマッピング​

Doris 4.2 のマッピング表、精度規則、サポートされない型の詳細は、Iceberg から Doris へのデータ型マッピングを参照してください。

カラム名の大文字と小文字​

Doris は Iceberg テーブルのカラム名の大文字と小文字を保持し、読み取り時には大文字と小文字を区別せずにカラムを照合します。UserId や ORDER_ID のように、大文字や大文字と小文字が混在するカラム名も正常にクエリできます。

バージョンに関する注記

4.0.8 より前のバージョンでは、読み取り時に完全一致でカラムを検索していたため、大文字と小文字が混在するカラム名を持つ Iceberg および Paimon テーブルでは、誤ったカラムを読み取ったりクエリが失敗したりする場合がありました。この問題は 4.0.8 で修正されました。

Namespace のマッピング​

Iceberg のメタデータ階層は Catalog -> Namespace -> Table です。Namespace は複数階層にできます(Nested Namespace)。

      ┌─────────┐
│ Catalog │
└────┬────┘
│
┌─────┴─────┐
┌──▼──┐ ┌──▼──┐
│ NS1 │ │ NS2 │
└──┬──┘ └──┬──┘
│ │
┌────▼───┐ ┌──▼──┐
│ Table1 │ │ NS3 │
└────────┘ └──┬──┘
│
┌──────┴───────┐
┌────▼───┐ ┌────▼───┐
│ Table2 │ │ Table3 │
└────────┘ └────────┘

バージョン 3.1.2 以降、Doris は Iceberg Rest Catalog の Nested Namespace のマッピングをサポートします。

上の例では、テーブルは次の規則で Doris のメタデータにマッピングされます。

Catalogデータベーステーブル
CatalogNS1Table1
CatalogNS2.NS3Table2
CatalogNS2.NS3Table3

Nested Namespace のサポートは明示的に有効にする必要があります。詳細は Iceberg Rest Catalog を参照してください。

例​

Hive Metastore​

バージョン 3.1 以降

Kerberos 認証を使用せずに HMS と HDFS のサービスへアクセス

CREATE CATALOG iceberg_hms_on_hdfs_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'hms',
'warehouse' = 'hdfs://127.0.0.1:8320/user/iceberg/warehouse/iceberg-hms-hdfs-warehouse',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'fs.defaultFS' = 'hdfs://127.0.0.1:8320',
'hadoop.username' = 'doris'
);

Kerberos 認証を有効にして HMS と HDFS のサービスへアクセス

CREATE CATALOG iceberg_hms_on_hdfs_kerberos_hdfs_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'hms',
'warehouse' = 'hdfs://127.0.0.1:8520/iceberg-hms-hdfs-warehouse',
'hive.metastore.uris' = 'thrift://127.0.0.1:9583',
'hive.metastore.client.principal' = 'hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hive.metastore.client.keytab' = '/keytabs/hive-presto-master.keytab',
'hive.metastore.service.principal' = 'hive/hadoop-master@LABS.TERADATA.COM',
'hive.metastore.sasl.enabled' = 'true',
'hive.metastore.authentication.type' = 'kerberos',
'hadoop.security.auth_to_local' = 'RULE:[2:\$1@\$0](.*@LABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERLABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERREALM.COM)s/@.*//
DEFAULT',
'fs.defaultFS' = 'hdfs://127.0.0.1:8520',
'hadoop.security.authentication' = 'kerberos',
'hadoop.kerberos.principal'='hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hadoop.kerberos.keytab' = '/keytabs/hive-presto-master.keytab'
);
バージョン 2.1 と 3.0

Kerberos 認証を使用せずに HMS と HDFS のサービスへアクセス

CREATE CATALOG iceberg_hms_on_hdfs_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'hms',
'hive.metastore.uris' = 'thrift://127.0.0.1:9383',
'warehouse' = 'hdfs://127.0.0.1:8320/user/iceberg/warehouse/iceberg-hms-hdfs-warehouse',
'hadoop.username' = 'doris',
'fs.defaultFS' = 'hdfs://127.0.0.1:8320'
);

Kerberos 認証を有効にして HMS と HDFS のサービスへアクセス

CREATE CATALOG iceberg_hms_on_hdfs_kerberos_hdfs_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'hms',
'warehouse' = 'hdfs://127.0.0.1:8520/iceberg-hms-hdfs-warehouse',
'hive.metastore.uris' = 'thrift://127.0.0.1:9583',
'hive.metastore.kerberos.principal' = 'hive/hadoop-master@LABS.TERADATA.COM',
'hive.metastore.sasl.enabled' = 'true',
'hive.metastore.authentication.type' = 'kerberos',
'hadoop.security.auth_to_local' = 'RULE:[2:\$1@\$0](.*@LABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERLABS.TERADATA.COM)s/@.*//
RULE:[2:\$1@\$0](.*@OTHERREALM.COM)s/@.*//
DEFAULT',
'fs.defaultFS' = 'hdfs://127.0.0.1:8520',
'hadoop.security.authentication' = 'kerberos',
'hadoop.kerberos.principal'='hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hadoop.kerberos.keytab' = '/keytabs/hive-presto-master.keytab'
);

AWS Glue​

バージョン 3.1 以降

AWS Glue と S3 ストレージサービスで同じ認証情報を共有する場合です。

CREATE CATALOG `iceberg_glue_on_s3_catalog_` PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'glue',
'warehouse' = 's3://bucket/iceberg-glue-s3-warehouse',
'glue.region' = 'ap-northeast-1',
'glue.endpoint' = 'https://glue.ap-northeast-1.amazonaws.com',
'glue.access_key' = '<ak>',
'glue.secret_key' = '<sk>'
);

Glue サービスと S3 の認証情報が異なる場合は、次の方法で S3 の認証情報を別途指定できます。

CREATE CATALOG `iceberg_glue_on_s3_catalog_` PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'glue',
'warehouse' = 's3://selectdb-qa-datalake-test/iceberg-glue-s3-warehouse',
'glue.region' = 'ap-northeast-1',
'glue.endpoint' = 'https://glue.ap-northeast-1.amazonaws.com',
'glue.access_key' = '<ak>',
'glue.secret_key' = '<sk>',
's3.endpoint' = 'https://s3.ap-northeast-1.amazonaws.com',
's3.region' = 'ap-northeast-1',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>'
);
CREATE CATALOG `glue_iceberg_iamrole` PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'glue',
'warehouse' = 's3://bucket/warehouse',
'glue.region' = 'us-east-1',
'glue.endpoint' = 'https://glue.us-east-1.amazonaws.com',
'glue.role_arn' = '<role_arn>'
);
バージョン 2.1 と 3.0

AWS Glue と S3 ストレージサービスで同じ認証情報を共有する場合です。

EC2 以外の環境では、aws configure を使用して認証情報を設定し、~/.aws ディレクトリに認証情報ファイルを生成する必要があります。

CREATE CATALOG glue PROPERTIES (
'type'='iceberg',
'iceberg.catalog.type' = 'glue',
'glue.endpoint' = 'https://glue.us-east-1.amazonaws.com',
'glue.access_key' = '<ak>',
'glue.secret_key' = '<sk>'
);

Aliyun DLF​

バージョン 4.1 以降
CREATE CATALOG iceberg_dlf2_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'rest',
'iceberg.rest.uri' = 'http://<region>-vpc.dlf.aliyuncs.com/iceberg',
'warehouse' = '<your-catalog-name>',
'iceberg.rest.sigv4-enabled' = 'true',
'iceberg.rest.signing-name' = 'DlfNext',
'iceberg.rest.access-key-id' = '<ak>',
'iceberg.rest.secret-access-key' = '<sk>',
'iceberg.rest.signing-region' = '<region>',
'iceberg.rest.vended-credentials-enabled' = 'true',
'io-impl' = 'org.apache.iceberg.rest.DlfFileIO',
'fs.oss.support' = 'true'
);
バージョン 3.1 以降
CREATE CATALOG iceberg_dlf_catalog_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'dlf',
'warehouse' = 'oss://bucket/iceberg-dlf-oss-warehouse',
'dlf.uid' = '203225413946383283',
'dlf.catalog_id' = 'p2_regression_case',
'dlf.region' = 'cn-beijing',
'dlf.endpoint' = 'datalake.cn-beijing.aliyuncs.com',
'dlf.access_key' = '<ak>',
'dlf.secret_key' = '<sk>'
);
バージョン 2.1 と 3.0
CREATE CATALOG iceberg_dlf_catalog_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'dlf',
'warehouse' = 'oss://bucket/iceberg-dlf-oss-warehouse',
'dlf.uid' = '203225413946383283',
'dlf.catalog.id' = 'catalog_id',
'dlf.region' = 'cn-beijing',
'dlf.access_key' = '<ak>',
'dlf.secret_key' = '<sk>'
);

Iceberg Rest Catalog​

動作の変更(4.1.4)

バージョン 4.1.4 以降、iceberg.rest.signing-name に glue、s3tables、osstables などのマネージド署名サービスを指定する場合は、'iceberg.rest.sigv4-enabled' = 'true' も必ず設定してください。設定しないと Catalog の作成時に次のエラーが発生します。

Rest Catalog requires sigv4-enabled set to true when signing-name is <name>

既存の Catalog で sigv4-enabled を有効にせず signing-name のみを設定している場合、アップグレード後に検証が失敗するため、このプロパティを追加する必要があります。

Alibaba Cloud OSS Tables​

バージョン 4.1.4 以降でサポートされます。

Alibaba Cloud OSS Tables への接続用に、iceberg.rest.signing-name に新しい値 osstables を指定できます。この場合、REST リクエストの署名には s3.* の認証情報ではなく、OSS の認証情報(oss.access_key、oss.secret_key、oss.session_token)が再利用されます。

CREATE CATALOG iceberg_osstables PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'rest',
'iceberg.rest.uri' = '<oss_tables_rest_endpoint>',
'warehouse' = '<your-catalog-name>',
'iceberg.rest.sigv4-enabled' = 'true',
'iceberg.rest.signing-name' = 'osstables',
'iceberg.rest.signing-region' = '<region>',
'oss.access_key' = '<ak>',
'oss.secret_key' = '<sk>',
'oss.endpoint' = 'oss-<region>.aliyuncs.com',
'oss.region' = '<region>'
);

osstables を使用する場合、iceberg.rest.signing-region と iceberg.rest.sigv4-enabled = 'true' の両方が必要です。設定しないと次のエラーが報告されます。

Rest Catalog requires signing-region and sigv4-enabled set to true when signing-name is osstables
バージョン 3.1 以降
CREATE CATALOG iceberg_static_s3 PROPERTIES (
'type' = 'iceberg',
'warehouse' = 's3://warehouse',
'iceberg.catalog.type' = 'rest',
'iceberg.rest.uri' = 'http://127.0.0.1:8181',
's3.endpoint' = 'https://s3.ap-east-1.amazonaws.com',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>',
's3.region' = 'ap-east-1'
);
バージョン 2.1 と 3.0
CREATE CATALOG iceberg_static_s3 PROPERTIES (
'type' = 'iceberg',
'warehouse' = 's3://warehouse',
'iceberg.catalog.type' = 'rest',
'uri' = 'http://127.0.0.1:8181',
's3.endpoint' = 'https://s3.ap-east-1.amazonaws.com',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>',
's3.region' = 'ap-east-1'
);

Iceberg JDBC Catalog​

注

これはバージョン 4.1.0 以降でサポートされる実験的な機能です。

バージョン 4.1 以降

PostgreSQL をメタデータストレージとして使用し、S3 と組み合わせる場合

CREATE CATALOG iceberg_jdbc_postgresql PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'jdbc',
'iceberg.jdbc.catalog_name' = 'iceberg_jdbc_postgresql',
'iceberg.jdbc.uri' = 'jdbc:postgresql://127.0.0.1:5432/iceberg_db',
'iceberg.jdbc.user' = 'iceberg_user',
'iceberg.jdbc.password' = 'password',
'iceberg.jdbc.init-catalog-tables' = 'true',
'iceberg.jdbc.schema-version' = 'V1',
'iceberg.jdbc.driver_class' = 'org.postgresql.Driver',
'iceberg.jdbc.driver_url' = '<jdbc_driver_jar>',
'warehouse' = 's3://bucket/warehouse',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>',
's3.endpoint' = 'https://s3.us-east-1.amazonaws.com',
's3.region' = 'us-east-1'
);

FileSystem​

バージョン 3.1 以降

Kerberos 認証を使用せずに HDFS サービスへアクセス

CREATE CATALOG iceberg_fs_on_hdfs_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'hadoop',
'warehouse' = 'hdfs://127.0.0.1:8320/user/iceberg/warehouse/iceberg-fs-hdfs-warehouse',
'hadoop.username' = 'doris',
'fs.defaultFS' = 'hdfs://127.0.0.1:8320'
);

Kerberos 認証を有効にして HDFS サービスへアクセス

CREATE CATALOG iceberg_fs_on_hdfs_kerberos_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'hadoop',
'warehouse' = 'hdfs://127.0.0.1:8520/iceberg-fs-hdfs-warehouse',
'fs.defaultFS' = 'hdfs://127.0.0.1:8520',
'hadoop.security.authentication' = 'kerberos',
'hadoop.kerberos.principal' = 'hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hadoop.kerberos.keytab' = '/keytabs/hive-presto-master.keytab'
);

バージョン 2.1 と 3.0

Kerberos 認証を使用せずに HDFS サービスへアクセス

CREATE CATALOG iceberg_fs_on_hdfs_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'hadoop',
'warehouse' = 'hdfs://127.0.0.1:8320/user/iceberg/warehouse/iceberg-fs-hdfs-warehouse',
'hadoop.username' = 'doris',
'fs.defaultFS' = 'hdfs://127.0.0.1:8320'
);

Kerberos 認証を有効にして HDFS サービスへアクセス

CREATE CATALOG iceberg_fs_on_hdfs_kerberos_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'hadoop',
'warehouse' = 'hdfs://127.0.0.1:8520/iceberg-fs-hdfs-warehouse',
'fs.defaultFS' = 'hdfs://127.0.0.1:8520',
'hadoop.security.authentication' = 'kerberos',
'hadoop.kerberos.principal'='hive/presto-master.docker.cluster@LABS.TERADATA.COM',
'hadoop.kerberos.keytab' = '/keytabs/hive-presto-master.keytab'
);

AWS S3 Tables​

バージョン 3.1 以降

S3 Tables との連携のドキュメントを参照してください。

CREATE CATALOG aws_s3_tables PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'rest',
'warehouse' = 'arn:aws:s3tables:us-east-1:<account_id>:bucket/<s3_table_bucket_name>',
'iceberg.rest.uri' = 'https://s3tables.us-east-1.amazonaws.com/iceberg',
'iceberg.rest.sigv4-enabled' = 'true',
'iceberg.rest.signing-name' = 's3tables',
'iceberg.rest.signing-region' = 'us-east-1',
'iceberg.rest.access-key-id' = '<ak>',
'iceberg.rest.secret-access-key' = '<sk>'
);
バージョン 3.0.6 以降

S3 Tables との連携のドキュメントを参照してください。

CREATE CATALOG test_s3tables_catalog PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 's3tables',
'warehouse' = 'arn:aws:s3tables:ap-east-1:9527:bucket/doris-s3-table-bucket',
's3.region' = 'ap-east-1',
's3.endpoint' = 'https://s3.ap-east-1.amazonaws.com',
's3.access_key' = '<ak>',
's3.secret_key' = '<sk>'
);

Alibaba Cloud OSS Tables​

バージョン 4.1.4 以降

設定と使用方法の詳細は、Alibaba Cloud OSS Tables との連携を参照してください。

CREATE CATALOG oss_tables PROPERTIES (
'type' = 'iceberg',
'iceberg.catalog.type' = 'rest',
'iceberg.rest.uri' = 'https://<region>.oss-tables.aliyuncs.com/iceberg',
'warehouse' = 'acs:osstables:<region>:<account_id>:bucket/<table_bucket_name>',
'iceberg.rest.sigv4-enabled' = 'true',
'iceberg.rest.signing-name' = 'osstables',
'iceberg.rest.signing-region' = '<region>',
'iceberg.rest.view-enabled' = 'false',
'io-impl' = 'org.apache.iceberg.aws.s3.S3FileIO',
'oss.endpoint' = 'https://oss-<region>.aliyuncs.com',
'oss.region' = '<region>',
'oss.access_key' = '<access_key_id>',
'oss.secret_key' = '<access_key_secret>',
'oss.use_path_style' = 'false',
'test_connection' = 'true'
);

クエリ操作​

基本的なクエリ​

-- 1. switch to catalog, use database and query
SWITCH iceberg;
USE iceberg_db;
SELECT * FROM iceberg_tbl LIMIT 10;

-- 2. use iceberg database directly
USE iceberg.iceberg_db;
SELECT * FROM iceberg_tbl LIMIT 10;

-- 3. use full qualified name to query
SELECT * FROM iceberg.iceberg_db.iceberg_tbl LIMIT 10;

タイムトラベル​

Iceberg テーブルの特定のスナップショットを読み取れます。

デフォルトでは、読み取りリクエストは最新バージョンのスナップショットにアクセスします。

$snapshots システムテーブルを使用して、Iceberg テーブルのスナップショットをクエリできます。

動作の変更(4.1.4)

バージョン 4.1.4 以降、iceberg_meta() テーブル関数は削除されました。代わりに、Iceberg システムテーブル(例:iceberg_tbl$snapshots)を使用してメタデータをクエリしてください。後述のシステムテーブルを参照してください。

SELECT * FROM iceberg_ctl.iceberg_db.iceberg_tbl$snapshots\G

*************************** 1. row ***************************
committed_at: 2024-11-28 11:07:29
snapshot_id: 8903826400153112036
parent_id: -1
operation: append
manifest_list: oss://path/to/metadata/snap-8903826400153112036-1-3835e66d-9a18-4cb0-b9b0-9ec80527ad8d.avro
summary: {"added-data-files":"2","added-records":"3","added-files-size":"2742","changed-partition-count":"2","total-records":"3","total-files-size":"2742","total-data-files":"2","total-delete-files":"0","total-position-deletes":"0","total-equality-deletes":"0"}
*************************** 2. row ***************************
committed_at: 2024-11-28 11:10:11
snapshot_id: 6099853805930794326
parent_id: 8903826400153112036
operation: append
manifest_list: oss://path/to/metadata/snap-6099853805930794326-1-dd46a1bd-219b-4fb0-bb46-ac441d8b3105.avro
summary: {"added-data-files":"1","added-records":"1","added-files-size":"1367","changed-partition-count":"1","total-records":"4","total-files-size":"4109","total-data-files":"3","total-delete-files":"0","total-position-deletes":"0","total-equality-deletes":"0"}

FOR TIME AS OF と FOR VERSION AS OF 句を使用し、スナップショット ID または作成時刻を基準に過去のデータを読み取れます。例を示します。

-- Read data as of a specific timestamp
SELECT * FROM iceberg_table FOR TIME AS OF '2023-01-01 00:00:00';

-- Read data as of a specific snapshot ID
SELECT * FROM iceberg_table FOR VERSION AS OF 123456789;

4.1.5 以降、FOR TIME AS OF は yyyy-MM-dd HH:mm:ss の後に小数点以下 1~9 桁を受け付けます。値をセッションのタイムゾーンで解釈し、スナップショットの選択に使用するミリ秒に変換します。例:FOR TIME AS OF '2024-01-01 12:00:00.123456'。スナップショットの選択精度はミリ秒であり、この構文を受け付けてもナノ秒精度のスナップショット時刻が保持されるわけではありません。

Doris 4.1.5 では、カラム名の変更、削除、型の昇格、パーティション進化後の過去のスナップショットの読み取りも修正されました。各ファイルは現在の仕様だけでなく、そのファイルが書き込まれたときに有効だったパーティション仕様に従って解釈されます。過去のデータを対象とするクエリを、現在のマテリアライズドビューを読み取るように書き換えてはいけません。

Branch と Tag​

3.1.0 以降。

Branch と Tag の作成、削除、管理については、[Branch と Tag の管理]のセクションを参照してください。

Iceberg テーブルの特定の Branch と Tag の読み取りをサポートします。

Spark や Trino などのシステムとの互換性のため、複数の構文形式をサポートします。

-- BRANCH
SELECT * FROM iceberg_tbl@branch(branch1);
SELECT * FROM iceberg_tbl@branch("name" = "branch1");
SELECT * FROM iceberg_tbl FOR VERSION AS OF 'branch1';

-- TAG
SELECT * FROM iceberg_tbl@tag(tag1);
SELECT * FROM iceberg_tbl@tag("name" = "tag1");
SELECT * FROM iceberg_tbl FOR VERSION AS OF 'tag1';

FOR VERSION AS OF 構文では、Doris がパラメータをタイムスタンプまたは Branch/Tag 名のどちらとして扱うか自動判定します。

View​

3.1.0 以降

Iceberg View のクエリをサポートします。View のクエリ方法は通常のテーブルと同じです。次の点に注意してください。

  • hms 型の Iceberg Catalog のみサポートされます。
  • View 定義の SQL は Doris の SQL 方言と互換性が必要です。互換性がない場合、解析エラーが発生します(方言変換機能は今後のバージョンで提供予定です)。

Iceberg V3 の隠しカラム(Row Lineage)​

ヒント

これはバージョン 4.1.0 以降でサポートされる実験的な機能です。

Doris は Iceberg V3 テーブルの Row Lineage 隠しカラムをクエリできます。Iceberg V3 では、データ変更の記録を追跡する行系譜データを含むシステム隠しカラムが導入されました。これは増分同期やデータ監査に特に適しています。

  • _row_id:データ行を一意に識別する数値です(データが書き込まれたファイルと位置に基づいて生成されます)。
  • _last_updated_sequence_number:その行を最後に変更したときの Sequence Number です。UPDATE または MERGE INTO 操作でデータを更新すると、この数値はバージョン番号とともに自動的に増加します。

隠しカラムのクエリ方法:

デフォルトでは、DESC や SELECT * に隠しカラムは表示されません。カラム名を直接指定すれば、明示的にクエリできます。

SELECT id, _row_id, _last_updated_sequence_number FROM iceberg_tbl;

セッション変数 show_hidden_columns を有効にすると、DESC や SELECT * などの通常の表示にも隠しカラムを含められます。

SET show_hidden_columns = true;
DESC iceberg_tbl;

注意事項:

  1. これらの行単位のパラメータを生成するには、Iceberg テーブルの形式バージョン(format-version)を 3 に設定する必要があります。V1/V2 形式のテーブルで Row Lineage カラムをクエリすると、エラーが発生する場合があります。
  2. 隠しカラムはシステムが管理します。ユーザーは、INSERT などの書き込み文で _row_id や _last_updated_sequence_number カラムを明示的に指定したり、書き込んだりできません。バージョン 4.1.4 以降では、format-version >= 3 のテーブルに対する INSERT 文のカラム一覧に Row Lineage カラムを指定すると、直ちに Cannot specify row lineage column '<name>' in INSERT statement で失敗します。

Iceberg V3 のデフォルト値​

バージョン 4.1.4 以降でサポートされます。

Iceberg V3 は 2 種類のカラムデフォルト値を定義し、Doris は両方をサポートします。

  • initial-default:カラム追加時に既存の過去のデータに割り当てられるデフォルト値です。カラムが存在する前に書き込まれた古いデータファイルを読み取る際、Doris は NULL の代わりにこのデフォルト値を返します。Parquet と ORC の両方に対応し、最上位のカラム、STRUCT 内のネストしたサブフィールド、全体が欠けている複合型の親カラムに適用されます。述語評価時にも有効です。
  • write-default:書き込み時に指定されていないカラムへ設定されるデフォルト値です。INSERT INTO t (subset of columns) VALUES (...) では、一覧にないカラムに現在の write-default が書き込まれます(以前のバージョンでは NULL が書き込まれました)。

DDL によるデフォルト値の指定:

ALTER TABLE iceberg_tbl ADD COLUMN c1 INT DEFAULT 10;

この文は Iceberg の write-default と initial-default の両方を設定します。テーブルの format-version が 3 であることが必要です。V1/V2 テーブルでは NULL 以外のデフォルト値を持つカラムをサポートしません。

DEFAULT() 式:

バージョン 4.1.4 以降、DML でカラムのデフォルト値を明示的に参照する DEFAULT(<column>) 式が利用できます。INSERT、UPDATE ... SET、MERGE INTO の各分岐で使用できます。

INSERT INTO iceberg_tbl VALUES (1, DEFAULT(c1));

UPDATE iceberg_tbl SET c1 = DEFAULT(c1) WHERE id = 1;

MERGE INTO iceberg_tbl t USING src s ON t.id = s.id
WHEN NOT MATCHED THEN INSERT VALUES (s.id, DEFAULT(c1));

動作は次のとおりです。

  • 書き込み先が Iceberg テーブルの場合、DEFAULT() はその書き込み用に固定された Iceberg スキーマに対して解決されます。書き込み先に含まれないカラムを参照すると、DEFAULT(<col>) must reference a column in the pinned Iceberg write target が報告されます。
  • Iceberg 以外のカラムには、そのカラムのデフォルト値が使用されます。デフォルト値がなく、NOT NULL または自動インクリメントの場合、Column '<name>' has no default value and does not allow NULL or column is auto-increment が発生します。NULL を許容し、デフォルト値がない場合は NULL が使用されます。
  • その他のエラーには、DEFAULT requires a column reference, but got: <expr>、Cannot find column information for DEFAULT(<name>)、DEFAULT cannot be used on generated column '<name>' があります。
注

Iceberg の write-default は書き込み側コネクタの概念です。DESCRIBE、SHOW CREATE TABLE、information_schema.columns.COLUMN_DEFAULT には公開されません。

システムテーブル​

3.1.0 以降

Doris は Iceberg システムテーブルへのクエリをサポートし、テーブルのメタデータ情報を取得できます。システムテーブルでスナップショット履歴、マニフェストファイル、データファイル、パーティションなどのメタデータを確認できます。

Iceberg テーブルのメタデータにアクセスするには、テーブル名の末尾に $ とシステムテーブル名を追加します。

SELECT * FROM iceberg_table$system_table_name;

たとえば、テーブルの履歴を表示するには、次を実行します。

SELECT * FROM iceberg_table$history;

all_manifests システムテーブルはバージョン 4.0.4 以降でサポートされます。

position_deletes システムテーブルはバージョン 4.1.4 以降でサポートされます。

動作の変更(4.1.4)

バージョン 4.1.4 以降、Iceberg システムテーブルはネイティブの実行経路(FileQueryScanNode -> IcebergScanNode)を通じてクエリされ、iceberg_meta() テーブル関数は削除されました。代わりに <table>$<system_table_name> というシステムテーブル構文を使用してください。ICEBERG_META を参照してください。

システムテーブルのアクセス構文と返される結果自体は変わりません。また、システムテーブルは SHOW CREATE TABLE に対応しました。

entries​

テーブルの現在のスナップショットに含まれるすべてのマニフェストエントリを表示します。

all_entries と entries は似ていますが、all_entries にはすべてのスナップショットのエントリが含まれ、entries には現在のスナップショットのエントリのみが含まれます。

SELECT * FROM iceberg_table$entries;

結果:

+--------+---------------------+-----------------+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| status | snapshot_id | sequence_number | file_sequence_number | data_file | readable_metrics |
+--------+---------------------+-----------------+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2 | 4890031351138056789 | 1 | 1 | {"content":0, "file_path":"s3://.../iceberg_table/data/id=1/00000-16-79ef2fd7-9997-47eb-a91a-9f7af8201315-0-00001.parquet", "file_format":"PARQUET", "spec_id":0, "partition":{"id":1}, "record_count":1, "file_size_in_bytes":625, "column_sizes":{1:36, 2:41}, "value_counts":{1:1, 2:1}, "null_value_counts":{1:0, 2:0}, "nan_value_counts":{}, "lower_bounds":{1:" ", 2:"Alice"}, "upper_bounds":{1:" ", 2:"Alice"}, "key_metadata":null, "split_offsets":[4], "equality_ids":null, "sort_order_id":0, "first_row_id":null, "referenced_data_file":null, "content_offset":null, "content_size_in_bytes":null} | {"id":{"column_size":36, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":1, "upper_bound":1}, "name":{"column_size":41, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":"Alice", "upper_bound":"Alice"}} |
| 0 | 1851184769713369003 | 1 | 1 | {"content":0, "file_path":"s3://.../iceberg_table/data/id=2/00000-16-79ef2fd7-9997-47eb-a91a-9f7af8201315-0-00002.parquet", "file_format":"PARQUET", "spec_id":0, "partition":{"id":2}, "record_count":1, "file_size_in_bytes":611, "column_sizes":{1:36, 2:39}, "value_counts":{1:1, 2:1}, "null_value_counts":{1:0, 2:0}, "nan_value_counts":{}, "lower_bounds":{1:" ", 2:"Bob"}, "upper_bounds":{1:" ", 2:"Bob"}, "key_metadata":null, "split_offsets":[4], "equality_ids":null, "sort_order_id":0, "first_row_id":null, "referenced_data_file":null, "content_offset":null, "content_size_in_bytes":null} | {"id":{"column_size":36, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":2, "upper_bound":2}, "name":{"column_size":39, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":"Bob", "upper_bound":"Bob"}} |
+--------+---------------------+-----------------+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

files​

テーブルの現在のスナップショットのファイル一覧を表示します。

SELECT * FROM iceberg_table$files;

結果:

+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+-----------+--------------+--------------------+--------------+--------------+-------------------+------------------+-----------------------+-----------------------+--------------+---------------+--------------+---------------+--------------+----------------------+----------------+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| content | file_path | file_format | spec_id | partition | record_count | file_size_in_bytes | column_sizes | value_counts | null_value_counts | nan_value_counts | lower_bounds | upper_bounds | key_metadata | split_offsets | equality_ids | sort_order_id | first_row_id | referenced_data_file | content_offset | content_size_in_bytes | readable_metrics |
+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+-----------+--------------+--------------------+--------------+--------------+-------------------+------------------+-----------------------+-----------------------+--------------+---------------+--------------+---------------+--------------+----------------------+----------------+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 0 | s3://.../iceberg_table/data/id=2/00000-16-79ef2fd7-9997-47eb-a91a-9f7af8201315-0-00002.parquet | PARQUET | 0 | {"id":2} | 1 | 611 | {1:36, 2:39} | {1:1, 2:1} | {1:0, 2:0} | {} | {1:" ", 2:"Bob"} | {1:" ", 2:"Bob"} | NULL | [4] | NULL | 0 | NULL | NULL | NULL | NULL | {"id":{"column_size":36, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":2, "upper_bound":2}, "name":{"column_size":39, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":"Bob", "upper_bound":"Bob"}} |
| 0 | s3://.../iceberg_table/data/id=4/00000-16-79ef2fd7-9997-47eb-a91a-9f7af8201315-0-00004.parquet | PARQUET | 0 | {"id":4} | 1 | 618 | {1:36, 2:40} | {1:1, 2:1} | {1:0, 2:0} | {} | {1:" ", 2:"Dave"} | {1:" ", 2:"Dave"} | NULL | [4] | NULL | 0 | NULL | NULL | NULL | NULL | {"id":{"column_size":36, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":4, "upper_bound":4}, "name":{"column_size":40, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":"Dave", "upper_bound":"Dave"}} |
| 0 | s3://.../iceberg_table/data/id=6/00000-16-79ef2fd7-9997-47eb-a91a-9f7af8201315-0-00006.parquet | PARQUET | 0 | {"id":6} | 1 | 625 | {1:36, 2:41} | {1:1, 2:1} | {1:0, 2:0} | {} | {1:" ", 2:"Frank"} | {1:" ", 2:"Frank"} | NULL | [4] | NULL | 0 | NULL | NULL | NULL | NULL | {"id":{"column_size":36, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":6, "upper_bound":6}, "name":{"column_size":41, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":"Frank", "upper_bound":"Frank"}} |
| 0 | s3://.../iceberg_table/data/id=8/00000-16-79ef2fd7-9997-47eb-a91a-9f7af8201315-0-00008.parquet | PARQUET | 0 | {"id":8} | 1 | 625 | {1:36, 2:41} | {1:1, 2:1} | {1:0, 2:0} | {} | {1:" ", 2:"Heidi"} | {1:" ", 2:"Heidi"} | NULL | [4] | NULL | 0 | NULL | NULL | NULL | NULL | {"id":{"column_size":36, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":8, "upper_bound":8}, "name":{"column_size":41, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":"Heidi", "upper_bound":"Heidi"}} |
| 0 | s3://.../iceberg_table/data/id=10/00000-16-79ef2fd7-9997-47eb-a91a-9f7af8201315-0-00010.parquet | PARQUET | 0 | {"id":10} | 1 | 618 | {1:36, 2:40} | {1:1, 2:1} | {1:0, 2:0} | {} | {1:" ", 2:"Judy"} | {1:" ", 2:"Judy"} | NULL | [4] | NULL | 0 | NULL | NULL | NULL | NULL | {"id":{"column_size":36, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":10, "upper_bound":10}, "name":{"column_size":40, "value_count":1, "null_value_count":0, "nan_value_count":null, "lower_bound":"Judy", "upper_bound":"Judy"}} |
+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+-----------+--------------+--------------------+--------------+--------------+-------------------+------------------+-----------------------+-----------------------+--------------+---------------+--------------+---------------+--------------+----------------------+----------------+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

files システムテーブルと同様に、次のシステムテーブルから特定の種類のファイル情報もクエリできます。

-- Query data files for the current snapshot
SELECT * FROM iceberg_table$data_files;

-- Query delete files for the current snapshot
SELECT * FROM iceberg_table$delete_files;

-- Query all files (including data and delete files) from all snapshots
SELECT * FROM iceberg_table$all_files;

-- Query data files from all snapshots
SELECT * FROM iceberg_table$all_data_files;

-- Query delete files from all snapshots
SELECT * FROM iceberg_table$all_delete_files;

これらのテーブルの結果形式は files システムテーブルと似ていますが、それぞれデータファイルまたは削除ファイルに対象を絞ります。all_ プレフィックスを持つシステムテーブルには、現在のスナップショットだけでなく、すべてのスナップショットのファイルが含まれます。

注:テーブルに特定の種類のファイルが存在しない場合(たとえば削除ファイルがないテーブルで delete_files をクエリする場合)、結果は空になることがあります。

history​

テーブルのすべての履歴を表示します。

SELECT * FROM iceberg_table$history;

結果:

+----------------------------+---------------------+---------------------+---------------------+
| made_current_at | snapshot_id | parent_id | is_current_ancestor |
+----------------------------+---------------------+---------------------+---------------------+
| 2025-06-12 22:29:16.357000 | 1851184769713369003 | NULL | 1 |
| 2025-06-12 22:29:39.922000 | 4890031351138056789 | 1851184769713369003 | 1 |
+----------------------------+---------------------+---------------------+---------------------+

manifests​

テーブルのマニフェストファイル情報を表示します。

SELECT * FROM iceberg_table$manifests;

結果:

+---------+------------------------------------------------------------------------------------------------------------------------------------------------+--------+-------------------+---------------------+------------------------+---------------------------+--------------------------+--------------------------+-----------------------------+----------------------------+--------------------------------------------------------------------------------+
| content | path | length | partition_spec_id | added_snapshot_id | added_data_files_count | existing_data_files_count | deleted_data_files_count | added_delete_files_count | existing_delete_files_count | deleted_delete_files_count | partition_summaries |
+---------+------------------------------------------------------------------------------------------------------------------------------------------------+--------+-------------------+---------------------+------------------------+---------------------------+--------------------------+--------------------------+-----------------------------+----------------------------+--------------------------------------------------------------------------------+
| 0 | s3://.../iceberg_table/metadata/3194eb8b-5ea4-4cbe-95ba-073229458e7b-m0.avro | 7138 | 0 | 4890031351138056789 | 0 | 5 | 5 | 0 | 0 | 0 | [{"contains_null":0, "contains_nan":0, "lower_bound":"1", "upper_bound":"10"}] |
+---------+------------------------------------------------------------------------------------------------------------------------------------------------+--------+-------------------+---------------------+------------------------+---------------------------+--------------------------+--------------------------+-----------------------------+----------------------------+--------------------------------------------------------------------------------+

all_manifests​

この機能はバージョン 4.0.4 以降でサポートされます。

テーブルのすべての有効なスナップショットのマニフェストファイル情報を表示します。

all_manifests と manifests は同じ構造です。all_manifests にはすべての有効なスナップショットのマニフェストファイルが含まれ、manifests には現在のスナップショットのマニフェストファイルのみが含まれます。

SELECT * FROM iceberg_table$all_manifests;

結果の形式は manifests システムテーブルと同じです。

metadata_log_entries​

テーブルのメタデータログを表示します。

SELECT * FROM iceberg_table$metadata_log_entries;

結果:

+----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+------------------+------------------------+
| timestamp | file | latest_snapshot_id | latest_schema_id | latest_sequence_number |
+----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+------------------+------------------------+
| 2025-06-12 22:29:06.948000 | s3://.../iceberg_table/metadata/00000-e373aa16-15f1-4e69-ae7d-5ed64199cf9a.metadata.json | NULL | NULL | NULL |
| 2025-06-12 22:29:16.357000 | s3://.../iceberg_table/metadata/00001-bbc8e244-e41c-4958-92f4-63b8c3ee1196.metadata.json | 1851184769713369003 | 0 | 1 |
| 2025-06-12 22:29:39.922000 | s3://.../iceberg_table/metadata/00002-7dc00d6a-6269-4200-9d28-5f8c1c6b9f99.metadata.json | 4890031351138056789 | 0 | 2 |
+----------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------+------------------+------------------------+

partitions​

テーブルのパーティションを表示します。

SELECT * FROM iceberg_table$partitions;

結果:

+-----------+---------+--------------+------------+-------------------------------+------------------------------+----------------------------+------------------------------+----------------------------+----------------------------+--------------------------+
| partition | spec_id | record_count | file_count | total_data_file_size_in_bytes | position_delete_record_count | position_delete_file_count | equality_delete_record_count | equality_delete_file_count | last_updated_at | last_updated_snapshot_id |
+-----------+---------+--------------+------------+-------------------------------+------------------------------+----------------------------+------------------------------+----------------------------+----------------------------+--------------------------+
| {"id":8} | 0 | 1 | 1 | 625 | 0 | 0 | 0 | 0 | 2025-06-12 22:29:16.357000 | 1851184769713369003 |
| {"id":6} | 0 | 1 | 1 | 625 | 0 | 0 | 0 | 0 | 2025-06-12 22:29:16.357000 | 1851184769713369003 |
| {"id":10} | 0 | 1 | 1 | 618 | 0 | 0 | 0 | 0 | 2025-06-12 22:29:16.357000 | 1851184769713369003 |
| {"id":4} | 0 | 1 | 1 | 618 | 0 | 0 | 0 | 0 | 2025-06-12 22:29:16.357000 | 1851184769713369003 |
| {"id":2} | 0 | 1 | 1 | 611 | 0 | 0 | 0 | 0 | 2025-06-12 22:29:16.357000 | 1851184769713369003 |
+-----------+---------+--------------+------------+-------------------------------+------------------------------+----------------------------+------------------------------+----------------------------+----------------------------+--------------------------+

注:

  1. パーティション分割されていないテーブルでは、partitions テーブルに partition と spec_id フィールドは含まれません。
  2. partitions テーブルには、現在のスナップショットでデータファイルまたは削除ファイルを含むパーティションが表示されます。ただし、削除ファイルは適用されません。そのため、パーティション内のすべてのデータ行が削除ファイルによって削除済みとマークされていても、そのパーティションが表示される場合があります。

refs​

テーブルに存在する既知のスナップショット参照(Branch と Tag)をすべて表示します。

SELECT * FROM iceberg_table$refs;

結果:

+------+--------+---------------------+-------------------------+-----------------------+------------------------+
| name | type | snapshot_id | max_reference_age_in_ms | min_snapshots_to_keep | max_snapshot_age_in_ms |
+------+--------+---------------------+-------------------------+-----------------------+------------------------+
| main | BRANCH | 4890031351138056789 | NULL | NULL | NULL |
+------+--------+---------------------+-------------------------+-----------------------+------------------------+

snapshots​

テーブルのすべてのスナップショットを表示します。

SELECT * FROM iceberg_table$snapshots;

結果:

+----------------------------+---------------------+---------------------+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| committed_at | snapshot_id | parent_id | operation | manifest_list | summary |
+----------------------------+---------------------+---------------------+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 2025-06-12 22:29:16.357000 | 1851184769713369003 | NULL | append | s3://.../iceberg_table/metadata/snap-1851184769713369003-1-82059f57-821a-4983-b083-002cc2cde313.avro | {"spark.app.id":"application_1738810850199_0472", "added-data-files":"10", "added-records":"10", "added-files-size":"6200", "changed-partition-count":"10", "total-records":"10", "total-files-size":"6200", "total-data-files":"10", "total-delete-files":"0", "total-position-deletes":"0", "total-equality-deletes":"0"} |
| 2025-06-12 22:29:39.922000 | 4890031351138056789 | 1851184769713369003 | overwrite | s3://.../iceberg_table/metadata/snap-4890031351138056789-1-3194eb8b-5ea4-4cbe-95ba-073229458e7b.avro | {"spark.app.id":"application_1738810850199_0472", "deleted-data-files":"5", "deleted-records":"5", "removed-files-size":"3103", "changed-partition-count":"5", "total-records":"5", "total-files-size":"3097", "total-data-files":"5", "total-delete-files":"0", "total-position-deletes":"0", "total-equality-deletes":"0"} |
+----------------------------+---------------------+---------------------+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

書き込み操作​

INSERT INTO​

INSERT 操作は、対象テーブルにデータを追加します。

例:

INSERT INTO iceberg_tbl VALUES (val1, val2, val3, val4);
INSERT INTO iceberg.iceberg_db.iceberg_tbl SELECT col1, col2 FROM internal.db1.tbl1;

INSERT INTO iceberg_tbl(col1, col2) VALUES (val1, val2);
INSERT INTO iceberg_tbl(col1, col2, partition_col1, partition_col2) VALUES (1, 2, 'beijing', '2023-12-12');

バージョン 3.1.0 以降、指定した Branch へのデータ書き込みをサポートします。

INSERT INTO iceberg_tbl@branch(b1) values (val1, val2, val3, val4);
INSERT INTO iceberg_tbl@branch(b1) (col3, col4) values (val3, val4);

INSERT OVERWRITE​

INSERT OVERWRITE 操作は、テーブル内の既存データを新しいデータで完全に置き換えます。

INSERT OVERWRITE TABLE iceberg_tbl VALUES (val1, val2, val3, val4);
INSERT OVERWRITE TABLE iceberg.iceberg_db.iceberg_tbl(col1, col2) SELECT col1, col2 FROM internal.db1.tbl1;

バージョン 3.1.0 以降、指定した Branch へのデータ書き込みをサポートします。

INSERT OVERWRITE TABLE iceberg_tbl@branch(b1) values (val1, val2, val3, val4);
INSERT OVERWRITE TABLE iceberg_tbl@branch(b1) (col3, col4) values (val3, val4);

バージョン 4.1.0 以降、静的パーティション(またはハイブリッド)へのデータ書き込みをサポートします。

-- Full Static Partition
INSERT OVERWRITE TABLE iceberg_tbl PARTITION (dt='2025-01-25', region='bj')
SELECT id, name FROM source_table;

-- Hybrid Partition Mode: "dt" is static, "region" comes from SELECT dynamically
INSERT OVERWRITE TABLE iceberg_tbl PARTITION (dt='2025-01-25')
SELECT id, name, region FROM source_table;

CTAS​

CTAS(Create Table As Select)文を使用して Iceberg テーブルを作成し、データを書き込めます。

CREATE TABLE iceberg_ctas AS SELECT * FROM other_table;

CTAS では、ファイル形式、パーティション分割、その他のプロパティを指定できます。

CREATE TABLE iceberg_ctas
PARTITION BY LIST (pt1, pt2) ()
AS SELECT col1, pt1, pt2 FROM part_ctas_src WHERE col1 > 0;

CREATE TABLE iceberg.iceberg_db.iceberg_ctas (col1, col2, pt1)
PARTITION BY LIST (pt1) ()
PROPERTIES (
'write-format'='parquet',
'compression-codec'='zstd'
)
AS SELECT col1, pt1 AS col2, pt2 AS pt1 FROM test_ctas.part_ctas_src WHERE col1 > 0;

INSERT INTO BRANCH​

3.1.0 以降

INSERT INTO iceberg_table@branch(b1) SELECT * FROM other_table;
INSERT OVERWRITE TABLE iceberg_table@branch(b1) SELECT * FROM other_table;

DELETE​

ヒント

これはバージョン 4.1.0 以降でサポートされる実験的な機能です。

DELETE 操作は、指定した条件に一致する Iceberg テーブルのデータ行を削除します。主に次の仕組みを使用します。V2 形式のテーブルでは Position Delete ファイルを書き込み、V3 形式のテーブルでは Puffin 形式の Deletion Vectors ファイルを書き込みます。

前提条件:

  • Iceberg テーブルの形式バージョン(format-version)は 2 以上でなければなりません。V1 形式のテーブルは DELETE 操作をサポートしません。

構文:

DELETE FROM iceberg_tbl WHERE <condition>;

例:

-- Delete a single row
DELETE FROM iceberg_tbl WHERE id = 1;

-- Delete using multiple conditions
DELETE FROM iceberg_tbl WHERE age > 30 AND name = 'Bob';

-- Delete using a subquery
DELETE FROM iceberg_tbl WHERE id IN (SELECT id FROM other_table WHERE status = 'inactive');

パーティション分割されたテーブルでも使い方は同じです。

DELETE FROM iceberg_partition_tbl WHERE id = 10;

UPDATE​

ヒント

これはバージョン 4.1.0 以降でサポートされる実験的な機能です。

UPDATE 操作は、指定した条件に一致する Iceberg テーブルのデータ行を変更します。内部では、まず削除追跡情報(V2 では Position Delete ファイル、V3 では Puffin 形式の Deletion Vectors)を書き込んで古いデータ行を無効としてマークし、その後、更新済みの新しいデータファイルを追加します。V3 形式が有効な場合、新しく挿入された行の追跡値 _last_updated_sequence_number は自動的に進みます。

前提条件:

  • Iceberg テーブルの形式バージョン(format-version)は 2 以上でなければなりません。V1 形式のテーブルは UPDATE 操作をサポートしません。

構文:

UPDATE iceberg_tbl SET <column1> = <value1> [, <column2> = <value2>, ...] WHERE <condition>;

例:

-- Update a single column
UPDATE iceberg_tbl SET name = 'Alice_new' WHERE id = 1;

-- Update multiple columns
UPDATE iceberg_tbl SET name = 'Updated', age = 28 WHERE id = 2;

-- Update using expressions
UPDATE iceberg_tbl SET age = age * 2 + 1, name = concat(name, '-modified') WHERE id = 3;

-- Update using a subquery as condition
UPDATE iceberg_tbl SET name = 'UpdatedViaSubquery' WHERE id IN (SELECT id FROM other_table);

パーティション分割されたテーブルでも使い方は同じです。

UPDATE iceberg_partition_tbl SET name = 'Updated' WHERE id = 10;

MERGE INTO​

ヒント

これはバージョン 4.1.0 以降でサポートされる実験的な機能です。

MERGE INTO 操作は、ソースデータと対象の Iceberg テーブルを照合し、結果に応じて挿入、更新、削除を行います。データ同期や増分更新などのシナリオに適しています。

前提条件:

  • Iceberg テーブルの形式バージョン(format-version)は 2 以上でなければなりません。V1 形式のテーブルは MERGE INTO 操作をサポートしません。

構文:

MERGE INTO target_table t
USING <source> s
ON <merge_condition>
[WHEN MATCHED [AND <condition>] THEN DELETE]
[WHEN MATCHED [AND <condition>] THEN UPDATE SET <column1> = <value1> [, ...]]
[WHEN NOT MATCHED [AND <condition>] THEN INSERT (<columns>) VALUES (<values>)]

<source> にはサブクエリまたは別のテーブルを指定できます。

例:

  • すべての照合操作(更新、削除、挿入)を実行する例:

    MERGE INTO iceberg_tbl t
    USING (
    SELECT 1 AS id, 'Alice_new' AS name, 26 AS age, 'U' AS flag
    UNION ALL
    SELECT 2, 'Bob', 30, 'D'
    UNION ALL
    SELECT 4, 'Dora', 28, 'I'
    ) s
    ON t.id = s.id
    WHEN MATCHED AND s.flag = 'D' THEN DELETE
    WHEN MATCHED THEN UPDATE SET
    name = s.name,
    age = s.age
    WHEN NOT MATCHED THEN INSERT (id, name, age)
    VALUES (s.id, s.name, s.age);

    この例では、次の処理が行われます。

    • id = 2 の行は flag = 'D' のため削除されます。
    • id = 1 の行は新しい name と age に更新されます。
    • id = 4 の行は対象テーブルに存在しないため挿入されます。
  • 一致した行の更新のみを実行する例:

    MERGE INTO iceberg_tbl t
    USING (SELECT 1 AS id, 'Alice_matched' AS name, 26 AS age) s
    ON t.id = s.id
    WHEN MATCHED THEN UPDATE SET name = s.name, age = s.age;
  • 一致しなかった行の挿入のみを実行する例:

    MERGE INTO iceberg_tbl t
    USING (SELECT 4 AS id, 'Dora' AS name, 40 AS age) s
    ON t.id = s.id
    WHEN NOT MATCHED THEN INSERT (id, name, age) VALUES (s.id, s.name, s.age);
  • サブクエリをデータソースとして使用する例:

    MERGE INTO iceberg_tbl t
    USING (SELECT id FROM other_table WHERE id = 2) s
    ON t.id = s.id
    WHEN MATCHED THEN UPDATE SET name = 'UpdatedViaSubquery';
  • パーティション分割されたテーブルに対する MERGE INTO 操作:

    MERGE INTO iceberg_partition_tbl t
    USING (
    SELECT 1 AS id, 'Alice_new' AS name, 26 AS age, DATE '2024-01-01' AS dt, 'U' AS flag
    UNION ALL
    SELECT 2, 'Bob', 30, DATE '2024-01-02', 'D'
    UNION ALL
    SELECT 4, 'Dora', 28, DATE '2024-01-04', 'I'
    ) s
    ON t.id = s.id
    WHEN MATCHED AND s.flag = 'D' THEN DELETE
    WHEN MATCHED THEN UPDATE SET
    name = s.name,
    age = s.age
    WHEN NOT MATCHED THEN INSERT (id, name, age, dt)
    VALUES (s.id, s.name, s.age, s.dt);

注意事項:

  1. 上記 3 つの操作(DELETE、UPDATE、MERGE INTO)はすべて、Iceberg テーブルの形式バージョン(format-version)が 2 以上であることを必要とします。V1 形式のテーブルで実行すると、must have format version 2 or higher for position deletes というエラーが発生します。V3 形式のテーブルで実行すると、システムは従来の Position Delete データを Puffin 形式の Deletion Vectors で置き換え、内容を更新した場合は書き込まれたレコードの系譜ライフサイクル属性(_last_updated_sequence_number)も自動的に調整します。
  2. これらの操作は Parquet と ORC の両方のファイル形式に対応します。
  3. 同時書き込みでは、Iceberg は楽観的同時実行制御を提供します。書き込み競合が発生すると、トランザクション競合の例外がスローされる場合があります。
  4. UPDATE 操作は、単独でも MERGE INTO 内でも、age = age * 2 + 1 や name = concat(name, '-modified') などの式や関数を使用できます。
  5. これらの操作は、パーティション分割されたテーブルとされていないテーブルの両方に適用できます。
  6. バージョン 4.1.4 以降(すべての BE のアップグレードが必要)、MERGE INTO はソースと対象テーブルの照合関係を検証します。同じ対象行に複数のソース行が一致すると、結果が不確定になる代わりに、multiple source rows matched the same target row で文が失敗します。1 対多の一致が想定される場合は、先にソース側で重複を除去してください。
  • BE(Backend)

    パラメータ名デフォルト値説明
    iceberg_sink_max_file_size1GBデータファイルの最大サイズです。書き込むデータがこのサイズを超えると、現在のファイルを閉じ、新しいファイルを作成して書き込みを続けます。
    table_sink_partition_write_max_partition_nums_per_writer128BE ノード上で各インスタンスが書き込めるパーティションの最大数です。
    table_sink_non_partition_write_scaling_data_processed_threshold25MBパーティション分割されていないテーブルで、書き込みのスケーリングを開始するデータ量のしきい値です。table_sink_non_partition_write_scaling_data_processed_threshold のデータ量が増えるたびに、新しいライター(インスタンス)が使用されます。この仕組みはデータ量に応じてライター数を調整し、スループットを高める一方、データ量が少ない場合はリソース消費とファイル数を抑えます。
    table_sink_partition_write_min_data_processed_rebalance_threshold25MBパーティション分割されたテーブルで再バランスを開始する最小データ量のしきい値です。current accumulated data volume - data volume since last rebalancing >= table_sink_partition_write_min_data_processed_rebalance_threshold の場合に開始します。このしきい値を下げると、ファイルサイズの差が大きい場合のバランスを改善できますが、再バランスのコストが増えて性能に影響する可能性があります。
    table_sink_partition_write_min_partition_data_processed_rebalance_threshold再バランスを開始するパーティションデータ量の最小しきい値です。current partition data volume >= threshold * number of tasks already allocated to the partition の場合に開始します。このしきい値を下げると、ファイルサイズの差が大きい場合のバランスを改善できますが、再バランスのコストが増えて性能に影響する可能性があります。

データベースとテーブルの管理​

データベースの作成と削除​

SWITCH 文で目的の Catalog に切り替え、CREATE DATABASE コマンドを実行できます。

SWITCH iceberg;
CREATE DATABASE [IF NOT EXISTS] iceberg_db;

完全修飾名を使用してデータベースを作成したり、次のようにデータベースのプロパティを指定したりすることもできます。

CREATE DATABASE [IF NOT EXISTS] iceberg.iceberg_db;

CREATE DATABASE [IF NOT EXISTS] iceberg.iceberg_db
PROPERTIES ('location'='hdfs://172.21.16.47:4007/path/to/db/');

データベースプロパティのサポート一覧(バージョン 4.1.4 以降で拡張):

Catalog の種類(iceberg.catalog.type)一般的なデータベースプロパティlocation プロパティ
hmsサポートサポート
glueサポート(4.1.4 以降)サポート(4.1.4 以降)
jdbcサポート(4.1.4 以降)非サポート
hadoop / rest / dlf / s3tables非サポート非サポート

プロパティがサポートされない場合、次のエラーメッセージが報告されます。

  • 一般的なプロパティ:Not supported: create database with properties for iceberg catalog type: <type>
  • location プロパティ:Not supported: database property 'location' for iceberg catalog type: <type> because it does not determine the default table location

REST プロトコルではサーバーが namespace プロパティを無視できるため、REST Catalog はデータベースプロパティをサポートしません。

SHOW CREATE DATABASE コマンドでデータベースの場所を確認できます。

mysql> SHOW CREATE DATABASE iceberg_db;
+-------------+-------------------------------------------------------------------------------------------------+
| Database | Create Database |
+-------------+-------------------------------------------------------------------------------------------------+
| iceberg_db | CREATE DATABASE iceberg_db LOCATION 'hdfs://172.21.16.47:4007/usr/hive/warehouse/iceberg_db.db' |
+-------------+-------------------------------------------------------------------------------------------------+

データベースを削除するには、次を実行します。

DROP DATABASE [IF EXISTS] iceberg.iceberg_db;
注意

Iceberg データベースを削除するには、まずそのデータベース内のすべてのテーブルを削除する必要があります。そうしないとエラーが発生します。

テーブルの作成と削除​

  • テーブルの作成

    Doris は、Iceberg でパーティション分割されたテーブルとされていないテーブルの両方の作成をサポートします。

    例:

    -- Create unpartitioned iceberg table
    CREATE TABLE unpartitioned_table (
    `col1` BOOLEAN COMMENT 'col1',
    `col2` INT COMMENT 'col2',
    `col3` BIGINT COMMENT 'col3',
    `col4` FLOAT COMMENT 'col4',
    `col5` DOUBLE COMMENT 'col5',
    `col6` DECIMAL(9,4) COMMENT 'col6',
    `col7` STRING COMMENT 'col7',
    `col8` DATE COMMENT 'col8',
    `col9` DATETIME COMMENT 'col9'
    )
    PROPERTIES (
    'write-format'='parquet'
    );

    -- Create partitioned iceberg table
    -- The partition columns must be in table's column definition list
    CREATE TABLE partition_table (
    `ts` DATETIME COMMENT 'ts',
    `col1` BOOLEAN COMMENT 'col1',
    `col2` INT COMMENT 'col2',
    `col3` BIGINT COMMENT 'col3',
    `col4` FLOAT COMMENT 'col4',
    `col5` DOUBLE COMMENT 'col5',
    `col6` DECIMAL(9,4) COMMENT 'col6',
    `col7` STRING COMMENT 'col7',
    `col8` DATE COMMENT 'col8',
    `col9` DATETIME COMMENT 'col9',
    `pt1` STRING COMMENT 'pt1',
    `pt2` STRING COMMENT 'pt2'
    )
    PARTITION BY LIST (day(ts), pt1, pt2) ()
    PROPERTIES (
    'write-format'='orc',
    'compression-codec'='zlib'
    );

    バージョン 4.1.0 以降、Doris は Iceberg テーブルの作成時にソートカラムを指定できます。書き込み時には指定したソートカラムに従ってデータが並べ替えられ、クエリ性能の向上につながります。

    CREATE TABLE ordered_table (
    `id` int NULL,
    `name` text NULL,
    `score` double NULL,
    `create_time` datetimev2(6) NULL
    )
    ORDER BY (`id` ASC NULLS FIRST, `score` DESC NULLS LAST)
    PROPERTIES (
    "write-format" = "parquet",
    "write.parquet.compression-codec" = "zstd"
    );
    • ソートカラムを指定しない場合、書き込み時にソートされません。
    • デフォルトのソート順は ASC NULLS FIRST です。

    作成後は SHOW CREATE TABLE コマンドで Iceberg テーブルの作成文を確認できます。パーティション関数については、パーティション分割のセクションを参照してください。

  • テーブルの削除

    DROP TABLE 文で Iceberg テーブルを削除できます。テーブルを削除すると、パーティションデータを含むデータも削除されます。

    例:

    DROP TABLE [IF EXISTS] iceberg_tbl;
  • カラム型のマッピング

    カラム型のマッピングのセクションを参照してください。

  • パーティション分割

    Iceberg のパーティションの種類は、Doris の List パーティションに対応します。そのため、Doris で Iceberg のパーティション分割テーブルを作成する際は List パーティション構文を使用しますが、各パーティションを明示的に列挙する必要はありません。データ挿入時に、Doris がデータ値に基づいて対応する Iceberg パーティションを自動作成します。

    • 単一カラムまたは複数カラムによるパーティション分割テーブルの作成をサポートします。

    • パーティション変換関数をサポートし、Iceberg の暗黙的なパーティション分割とパーティション進化を利用できます。具体的な関数は、Iceberg partition transforms を参照してください。

      • year(ts) または years(ts)

      • month(ts) または months(ts)

      • day(ts) または days(ts) または date(ts)

      • hour(ts) または hours(ts) または date_hour(ts)

      • bucket(N, col)

      • truncate(L, col)

  • ファイル形式

    • Parquet(デフォルト)

      Doris が作成した Iceberg テーブルでは、Datetime は timestamp_ntz 型に対応します。

      3.1.0 より後のバージョンでは、Datetime 型を Parquet ファイルに書き込む際、物理型として INT96 ではなく INT64 を使用します。

      他のシステムが作成した Iceberg テーブルでは、timestamp と timestamp_ntz の両方が Doris の Datetime 型にマッピングされます。ただし、書き込み時には実際の型に基づいてタイムゾーン処理の要否を判断します。

    • ORC

  • 圧縮形式

    • Parquet:snappy、zstd(デフォルト)、plain(非圧縮)。

    • ORC:snappy、zlib(デフォルト)、zstd、plain(非圧縮)。

  • ストレージ媒体

    • HDFS

    • オブジェクトストレージ

スキーマの変更​

3.1.0 以降、Doris は Iceberg テーブルのスキーマ変更をサポートし、ALTER TABLE 文で変更できます。

サポートされるスキーマ変更操作は次のとおりです。

  • カラム名の変更

    RENAME COLUMN 句を使用してカラム名を変更します。バージョン 4.1.4 以降では、ネストした型の内部にあるカラムの名前変更をサポートし、TO キーワードは省略できます。

    ALTER TABLE iceberg_table RENAME COLUMN old_col_name TO new_col_name;

    -- Supported since 4.1.4: TO can be omitted
    ALTER TABLE iceberg_table RENAME COLUMN old_col_name new_col_name;

    -- Supported since 4.1.4: rename a nested field
    ALTER TABLE iceberg_table RENAME COLUMN s.old_field TO new_field;
  • カラムの追加

    ADD COLUMN で新しいカラムを追加します。バージョン 4.1.4 以降では、ドット区切りのパス(例:s.new_field)を使用して、ネストした型(STRUCT)に新しいカラムを追加できます。新しいネストしたフィールドは NULL を許容する必要があります。

    新しいカラムの追加時には、NULL 許容属性、デフォルト値、コメント、カラム位置を指定できます。

    ALTER TABLE iceberg_table ADD COLUMN col_name col_type [NULL|NOT NULL, [DEFAULT default_value, [COMMENT 'comment', [FIRST|AFTER col_name]]]];

    例:

    ALTER TABLE iceberg_table ADD COLUMN new_col STRING NOT NULL DEFAULT 'default_value' COMMENT 'This is a new col' AFTER old_col;
  • 複数カラムの追加

    ADD COLUMN で複数のカラムを追加することもできます。新しいカラムはテーブルの末尾に追加されます。複数カラムの追加ではカラム位置の指定はサポートされません。ネストした型への新しいカラムの追加もサポートされません。

    各カラムの構文は単一カラムの追加と同じです。

    ALTER TABLE iceberg_table ADD COLUMN (col_name1 col_type1 [NULL|NOT NULL, [DEFAULT default_value, [COMMENT 'comment']]], col_name2 col_type2 [NULL|NOT NULL, [DEFAULT default_value, [COMMENT 'comment']]] ...);
  • カラムの削除

    DROP COLUMN でカラムを削除します。バージョン 4.1.4 以降では、ドット区切りのパスを使用してネストした型内のカラムを削除できます。

    ALTER TABLE iceberg_table DROP COLUMN col_name;

    -- Supported since 4.1.4: drop a nested field
    ALTER TABLE iceberg_table DROP COLUMN s.field_name;
  • カラムの変更

    MODIFY COLUMN 文を使用して、型、NULL 許容属性、デフォルト値、コメント、カラム位置などの属性を変更します。

    バージョン 4.0.4 以降、Doris は複合型(STRUCT、ARRAY、MAP)の変更をサポートします。これには安全な型の昇格と struct フィールドの追加が含まれます。

    ネストした型でサポートされる安全な型の昇格:

    • INT -> BIGINT、LARGEINT
    • TINYINT -> SMALLINT、INT、BIGINT、LARGEINT
    • SMALLINT -> INT、BIGINT、LARGEINT
    • BIGINT -> LARGEINT
    • FLOAT -> DOUBLE
    • VARCHAR(n) -> VARCHAR(m)(m > n の場合)

    複合型の制約:

    • 新しいネストしたフィールドはすべて NULL を許容する必要があります。
    • 任意から必須への変更はできません。
    • 複合型のデフォルト値は NULL のみサポートされます。

    注:カラム属性を変更する際は、変更しない属性も元の値で明示的に指定してください。

    ALTER TABLE iceberg_table MODIFY COLUMN col_name col_type [NULL|NOT NULL, [DEFAULT default_value, [COMMENT 'comment', [FIRST|AFTER col_name]]]];

    例:

    CREATE TABLE iceberg_table (
    id INT,
    name STRING
    );
    -- Modify the id column type to BIGINT, set as NOT NULL, default value to 0, and add comment
    ALTER TABLE iceberg_table MODIFY COLUMN id BIGINT NOT NULL DEFAULT 0 COMMENT 'This is a modified id column';

    複合型を変更する例:

    -- Create Iceberg table with complex types
    CREATE TABLE iceberg_tbl (
    id BIGINT,
    user_info STRUCT<name:STRING, scores:ARRAY<INT>, age:INT>,
    dt STRING
    );

    -- Append a new field (email) to the STRUCT column
    ALTER TABLE iceberg_tbl MODIFY COLUMN user_info STRUCT<name:STRING, scores:ARRAY<INT>, age:INT, email:STRING>;

    -- Promote the nested ARRAY element type from INT to BIGINT
    ALTER TABLE iceberg_tbl MODIFY COLUMN user_info STRUCT<name:STRING, scores:ARRAY<BIGINT>, age:INT, email:STRING>;
  • カラムの並べ替え

    ORDER BY で新しいカラム順を指定して並べ替えます。

    ALTER TABLE iceberg_table ORDER BY (col_name1, col_name2, ...);

ネストしたカラムのスキーマ変更(4.1.4 以降)​

バージョン 4.1.4 以降、ADD COLUMN、DROP COLUMN、MODIFY COLUMN、RENAME COLUMN はいずれもドット区切りのパス(例:a.b.c)を受け付け、ネストしたフィールドを直接操作できます。この機能はIceberg テーブルのみに適用されます。その他の種類のテーブルで使用すると、Nested column path is only supported for Iceberg tables: ... が報告されます。

主な制約とエラー:

エラーメッセージ説明
New nested field '<path>' must be nullable新しく追加するネストしたフィールドは NULL を許容する必要があります。
Rollup is not supported for Iceberg column operationsRollup 句はサポートされません。
PROPERTIES are not supported for Iceberg column operationsPROPERTIES 句はサポートされません。
KEY is not supported for Iceberg ADD/MODIFY COLUMNKEY キーワードはサポートされません。
Generated columns are not supported for Iceberg ADD/MODIFY COLUMN生成カラムはサポートされません。
Modifying default values is not supported for Iceberg columns既存カラムのデフォルト値の変更はサポートされません。
ON UPDATE is not supported for Iceberg ADD COLUMNON UPDATE 句はサポートされません。
Modify column type from complex to primitive is not supported複合型からプリミティブ型への変更はサポートされません。
Cannot change MAP key type from ... / Cannot <op> MAP key nested columnMAP キーの型の変更や MAP キーに対するネストしたカラム操作はサポートされません。
Iceberg does not support comments on collection element or value fieldsコレクション要素や MAP 値のフィールドへのコメントはサポートされません。
Multiple Iceberg ALTER clauses are not supported when a statement ...ネストしたカラムを扱う文に指定できる ALTER 句は一つだけです。

テーブルプロパティの変更​

バージョン 4.1.4 以降でサポートされます。

ALTER TABLE ... SET (...) を使用して Iceberg テーブルのネイティブプロパティを変更できます。一つの文で複数のプロパティを設定できます。

ALTER TABLE iceberg_ctl.iceberg_db.iceberg_tbl SET (
'write.target-file-size-bytes' = '268435456',
'commit.manifest.min-count-to-merge' = '50'
);

注意事項:

  • すべてのプロパティは一つの Iceberg UpdateProperties トランザクションとしてアトミックにコミットされます。失敗した場合はどのプロパティも反映されず、FE メタデータの更新もトリガーされません。
  • Doris 独自の auto_analyze_policy プロパティを、コネクタのネイティブプロパティと同じ文で設定することはできません。設定すると auto_analyze_policy cannot be set with external table properties が報告されます。単独で設定する場合、値は引き続き enable / disable / base_on_catalog です。
  • Catalog がメタデータ書き込みを実装していない場合、Update table properties operation is not supported for catalog: <name> が報告されます。

パーティション進化​

バージョン 4.0.2 以降、Doris は ALTER 文による Iceberg テーブルのパーティション進化をサポートします。

サポートされるパーティション変換は次のとおりです。

変換構文例
bucketbucket(N, column)bucket(16, id)
truncatetruncate(N, column)truncate(10, name)
yearyear(column)year(ts)
monthmonth(column)month(ts)
dayday(column)day(ts)
hourhour(column)hour(ts)
identitycolumncategory

サポートされる操作は次のとおりです。

  • パーティションキーの追加

    -- use optional AS keyword to specify a custom name for the partition field
    ALTER TABLE table_name ADD PARTITION KEY partition_transform [AS key_name];

    -- example
    ALTER TABLE prod.db.sample ADD PARTITION KEY bucket(16, id);
    ALTER TABLE prod.db.sample ADD PARTITION KEY truncate(4, data);
    ALTER TABLE prod.db.sample ADD PARTITION KEY year(ts);
    -- use optional AS keyword to specify a custom name for the partition field
    ALTER TABLE prod.db.sample ADD PARTITION KEY bucket(16, id) AS shard;
  • パーティションキーの削除

    ALTER TABLE table_name DROP PARTITION KEY partition_transform|key_name;

    -- example
    ALTER TABLE prod.db.sample DROP PARTITION KEY catalog;
    ALTER TABLE prod.db.sample DROP PARTITION KEY bucket(16, id);
    ALTER TABLE prod.db.sample DROP PARTITION KEY truncate(4, data);
    ALTER TABLE prod.db.sample DROP PARTITION KEY year(ts);
    ALTER TABLE prod.db.sample DROP PARTITION KEY shard;
  • パーティションキーの置き換え

    -- use optional AS keyword to specify a custom name for the partition field
    ALTER TABLE table_name REPLACE PARTITION KEY key_name WITH partition_transform [AS key_name];

    -- example
    ALTER TABLE prod.db.sample REPLACE PARTITION KEY ts_day WITH day(ts);
    -- use optional AS keyword to specify a custom name for the new partition field
    ALTER TABLE prod.db.sample REPLACE PARTITION KEY ts_day WITH day(ts) AS day_of_ts;

Branch と Tag の管理​

3.1.0 以降

  • Branch の作成

    構文:

    ALTER TABLE [catalog.][database.]table_name
    CREATE [OR REPLACE] BRANCH [IF NOT EXISTS] <branch_name>
    [AS OF VERSION <snapshot_id>]
    [RETAIN <num> { DAYS | HOURS | MINUTES }]
    [WITH SNAPSHOT RETENTION { snapshotKeep | timeKeep }]

    snapshotKeep:
    <num> SNAPSHOTS [<num> { DAYS | HOURS | MINUTES }]

    timeKeep:
    <num> { DAYS | HOURS | MINUTES }

    例:

    -- Create branch "b1".
    ALTER TABLE tbl CREATE BRANCH b1;
    ALTER TABLE tb1 CREATE BRANCH IF NOT EXISTS b1;
    -- Create or replace branch "b1".
    ALTER TABLE tb1 CREATE OR REPLACE BRANCH b1;
    -- Create or replace branch "b1" based on snapshot "123456".
    ALTER TABLE tb1 CREATE OR REPLACE BRANCH b1 AS OF VERSION 123456;
    -- Create or replace branch "b1" based on snapshot "123456", branch retained for 1 day.
    ALTER TABLE tb1 CREATE OR REPLACE BRANCH b1 AS OF VERSION 123456 RETAIN 1 DAYS;
    -- Create branch "b1" based on snapshot "123456", branch retained for 30 days. Keep the latest 3 snapshots in the branch.
    ALTER TABLE tb1 CREATE BRANCH b1 AS OF VERSION 123456 RETAIN 30 DAYS WITH SNAPSHOT RETENTION 3 SNAPSHOTS;
    -- Create branch "b1" based on snapshot "123456", branch retained for 30 days. Snapshots in the branch are retained for at most 2 days.
    ALTER TABLE tb1 CREATE BRANCH b1 AS OF VERSION 123456 RETAIN 30 DAYS WITH SNAPSHOT RETENTION 2 DAYS;
    -- Create branch "b1" based on snapshot "123456", branch retained for 30 days. Keep the latest 3 snapshots in the branch, and snapshots in the branch are retained for at most 2 days.
    ALTER TABLE tb1 CREATE BRANCH b1 AS OF VERSION 123456 RETAIN 30 DAYS WITH SNAPSHOT RETENTION 3 SNAPSHOTS 2 DAYS;
  • Branch の削除

    構文:

    ALTER TABLE [catalog.][database.]table_name
    DROP BRANCH [IF EXISTS] <branch_name>;

    例:

    ALTER TABLE tbl DROP BRANCH b1;
  • Tag の作成

    構文:

    ALTER TABLE [catalog.][database.]table_name
    CREATE [OR REPLACE] TAG [IF NOT EXISTS] <tag_name>
    [AS OF VERSION <snapshot_id>]
    [RETAIN <num> { DAYS | HOURS | MINUTES }]

    例:

    -- Create tag "t1".
    ALTER TABLE tbl CREATE TAG t1;
    ALTER TABLE tb1 CREATE TAG IF NOT EXISTS t1;
    -- Create or replace tag "t1".
    ALTER TABLE tb1 CREATE OR REPLACE TAG t1;
    -- Create or replace tag "t1" based on snapshot "123456".
    ALTER TABLE tb1 CREATE OR REPLACE TAG b1 AS OF VERSION 123456;
    -- Create or replace tag "b1" based on snapshot "123456", tag retained for 1 day.
    ALTER TABLE tb1 CREATE OR REPLACE TAG b1 AS OF VERSION 123456 RETAIN 1 DAYS;
  • Tag の削除

    構文:

    ALTER TABLE [catalog.][database.]table_name
    DROP TAG [IF EXISTS] <tag_name>;

    例:

    ALTER TABLE tbl DROP TAG t1;

Iceberg テーブルのアクション​

この機能はバージョン 4.0.2 以降でサポートされます。各操作の具体的なバージョン要件を参照してください。

これは実験的な機能です。

Doris は ALTER TABLE EXECUTE 構文による Iceberg テーブルの特定のアクションの実行をサポートします。この構文は、テーブルの最適化やスナップショット管理など、さまざまな操作に共通のインターフェースを提供します。

ALTER TABLE [catalog.][database.]table_name
EXECUTE <action_name> ("key1" = "value1", "key2" = "value2", ...)
[WHERE <condition>]
  • action_name:実行する操作の名前
  • ("key1" = "value1", ...):キーと値のペアで指定する操作のパラメータ。パラメータ名は二重引用符で囲む必要があります。
  • [WHERE <condition>]:操作対象のパーティションまたはデータ範囲を指定する省略可能な WHERE 条件(一部の操作のみサポート)。

cherrypick_snapshot​

cherrypick_snapshot 操作は、指定したスナップショットの変更を現在のテーブル状態にマージし、元のスナップショットを変更または削除せずに新しいスナップショットを作成します。

対応バージョン:4.0.2 以降

構文:

ALTER TABLE [catalog.][database.]table_name
EXECUTE cherrypick_snapshot ("snapshot_id" = "<snapshot_id>")

パラメータ:

パラメータ型必須説明
snapshot_idLongはいマージするスナップショット ID

戻り値:

cherrypick_snapshot 操作を実行すると、次の 2 カラムを持つ結果セットが返されます。

カラム名型説明
source_snapshot_idBIGINTマージされたスナップショット ID
current_snapshot_idBIGINTマージ操作後に新しく作成され、現在のものとして設定されたスナップショット ID

例:

-- Merge changes from snapshot 123456789 into the current table state
ALTER TABLE iceberg_db.iceberg_table
EXECUTE cherrypick_snapshot ("snapshot_id" = "123456789");

注意事項:

  1. この操作は WHERE 条件をサポートしません。
  2. 指定したスナップショットが存在しない場合、操作は失敗します。
  3. マージ操作では新しいスナップショットを作成し、元のスナップショットは削除しません。

expire_snapshots​

expire_snapshots 操作は、Iceberg テーブルから古いスナップショットを削除してストレージ容量を解放し、メタデータの性能を改善します。この操作は Apache Iceberg Spark のプロシージャ仕様に従います。

対応バージョン:4.1.0 以降

構文:

ALTER TABLE [catalog.][database.]table_name
EXECUTE expire_snapshots ("key1" = "value1", "key2" = "value2", ...)

パラメータ:

パラメータ型必須説明
older_thanStringいいえスナップショットの有効期限を判定する時刻のしきい値。これより古いスナップショットを削除します。ISO 日時形式(例:2024-01-01T00:00:00)またはミリ秒のタイムスタンプに対応します。
retain_lastIntegerいいえ保持する祖先スナップショットの数。単独で指定した場合、older_than は自動的に現在時刻に設定されます。
snapshot_idsStringいいえ有効期限切れにする特定のスナップショット ID をカンマで区切った一覧。
max_concurrent_deletesIntegerいいえ削除操作に使用するスレッドプールのサイズ。
clean_expired_metadataBooleanいいえtrue にすると、未使用のパーティション仕様とスキーマをクリーンアップします。

戻り値:

expire_snapshots 操作を実行すると、次の 6 カラムを持つ結果セットが返されます。

カラム名型説明
deleted_data_files_countBIGINT削除されたデータファイルの数
deleted_position_delete_files_countBIGINT削除された Position Delete ファイルの数
deleted_equality_delete_files_countBIGINT削除された Equality Delete ファイルの数
deleted_manifest_files_countBIGINT削除されたマニフェストファイルの数
deleted_manifest_lists_countBIGINT削除されたマニフェストリストファイルの数
deleted_statistics_files_countBIGINT削除された統計ファイルの数

例:

-- Expire snapshots, keeping only the last 2
ALTER TABLE iceberg_db.iceberg_table
EXECUTE expire_snapshots ("retain_last" = "2");

-- Expire snapshots older than a specific timestamp
ALTER TABLE iceberg_db.iceberg_table
EXECUTE expire_snapshots ("older_than" = "2024-01-01T00:00:00");

-- Expire specific snapshots by ID
ALTER TABLE iceberg_db.iceberg_table
EXECUTE expire_snapshots ("snapshot_ids" = "123456789,987654321");

-- Combine parameters: expire snapshots older than 2024-06-01 but keep at least the last 5
ALTER TABLE iceberg_db.iceberg_table
EXECUTE expire_snapshots ("older_than" = "2024-06-01T00:00:00", "retain_last" = "5");

注意事項:

  1. この操作は WHERE 条件をサポートしません。
  2. older_than と retain_last の両方を指定した場合は両方の条件が適用されます。older_than より古く、かつ直近の retain_last 個に含まれないスナップショットのみが削除されます。
  3. snapshot_ids を単独で指定して、特定のスナップショットを削除できます。
  4. この操作はスナップショットと関連するデータファイルを完全に削除します。慎重に使用してください。
  5. 実行前に $snapshots システムテーブルをクエリし、テーブルのスナップショット情報を確認することを推奨します。

fast_forward​

fast_forward 操作は、一つの Branch の現在のスナップショットを、別の Branch の最新スナップショットまで進めます。

対応バージョン:4.0.2 以降

構文:

ALTER TABLE [catalog.][database.]table_name
EXECUTE fast_forward ("branch" = "<branch_name>", "to" = "<target_branch>")

パラメータ:

パラメータ型必須説明
branchStringはい進める Branch の名前
toStringはい対象の Branch 名。branch はこの Branch の最新スナップショットまで進められます。

戻り値:

fast_forward 操作を実行すると、次の 3 カラムを持つ結果セットが返されます。

カラム名型説明
branch_updatedSTRING進められた Branch の名前
previous_refBIGINT操作前に Branch が参照していたスナップショット ID(NULL の場合あり)
updated_refBIGINT操作後に Branch が参照するスナップショット ID

例:

-- Advance the feature branch to the latest snapshot of the main branch
ALTER TABLE iceberg_db.iceberg_table
EXECUTE fast_forward ("branch" = "feature", "to" = "main");

注意事項:

  1. この操作は WHERE 条件をサポートしません。
  2. 指定した Branch が存在しない場合、操作は失敗します。
  3. 進められるのは Branch のみで、Tag は対象になりません。

publish_changes​

publish_changes 操作は、Write-Audit-Publish(WAP)パターンの「Publish」ステップです。特定の wap.id 属性を持つスナップショットを見つけて現在のテーブル状態に追加します。これにより、検証後に「ステージング済み」のデータをアトミックに公開できます。

対応バージョン:4.1.0 以降

構文:

ALTER TABLE [catalog.][database.]table_name
EXECUTE publish_changes ("wap_id" = "<wap-id>")

パラメータ:

パラメータ型必須説明
wap_idStringはい公開するスナップショットの wap.id

戻り値:

publish_changes 操作を実行すると、次の 2 カラムを持つ結果セットが返されます。

カラム名型説明
previous_snapshot_idBIGINT公開前のスナップショット ID
current_snapshot_idBIGINT公開後の新しいスナップショット ID

例:

ALTER TABLE iceberg_db.iceberg_table
EXECUTE publish_changes ("wap_id" = "branch-123")

注意事項:

  1. この操作は WHERE 条件をサポートしません。
  2. 指定した wap.id が存在しない場合、操作は失敗します。

rewrite_data_files​

rewrite_data_files 操作は Iceberg テーブルのデータファイルを書き直して小さなファイルをまとめ、クエリ性能とストレージ効率を最適化します。この操作は同期的に実行されます。

対応バージョン:4.0.2 以降

構文:

ALTER TABLE [catalog.][database.]table_name
EXECUTE rewrite_data_files ("key1" = "value1", "key2" = "value2", ...) [WHERE <condition>]

パラメータ:

パラメータ型デフォルト値説明
target-file-size-bytesLong536870912 (512MB)出力ファイルの目標サイズ(バイト)。
min-file-size-bytesLongtarget-file-size-bytes * 0.75ファイルの最小サイズ(バイト)。これより小さいファイルを書き直します。未指定の場合、目標ファイルサイズの 75% がデフォルトです。
max-file-size-bytesLongtarget-file-size-bytes * 1.8ファイルの最大サイズ(バイト)。これより大きいファイルを分割します。未指定の場合、目標ファイルサイズの 180% がデフォルトです。
min-input-filesInteger5書き直しを開始する入力ファイルの最小数。書き直し対象のファイル数がこのしきい値に達した場合のみ実行します。
rewrite-allBooleanfalseファイルサイズに関係なく、すべてのファイルを書き直すかどうか。
max-file-group-size-bytesLong107374182400 (100GB)単一ファイルグループの最大サイズ(バイト)。一つの書き直しタスクで処理するデータ量を制限するために使用します。
delete-file-thresholdIntegerInteger.MAX_VALUE書き直しを開始するために必要な削除ファイルの最小数。
delete-ratio-thresholdDouble0.3書き直しを開始する削除済みレコードの割合の最小値(削除済みレコード数/総レコード数)。範囲:0.0 - 1.0。
output-spec-idLong2出力ファイルのパーティション仕様 ID。

戻り値:

rewrite_data_files 操作を実行すると、次の 4 カラムを持つ結果セットが返されます。

カラム名型説明
rewritten_data_files_countINT書き直されたデータファイルの数
added_data_files_countINT追加された新しいデータファイルの数
rewritten_bytes_countINT書き直されたバイト数
removed_delete_files_countBIGINT削除された削除ファイルの数

例:

-- Rewrite data files with default parameters
ALTER TABLE iceberg_db.iceberg_table EXECUTE rewrite_data_files();

-- Specify target file size and minimum input files
ALTER TABLE iceberg_db.iceberg_table
EXECUTE rewrite_data_files (
"target-file-size-bytes" = "134217728",
"min-input-files" = "10"
);

-- Rewrite data in specific partitions using WHERE condition
ALTER TABLE iceberg_db.iceberg_table
EXECUTE rewrite_data_files (
"target-file-size-bytes" = "268435456"
)
WHERE date_col = '2024-01-01';

-- Rewrite all files
ALTER TABLE iceberg_db.iceberg_table
EXECUTE rewrite_data_files (
"rewrite-all" = "true",
"target-file-size-bytes" = "536870912"
);

注意事項:

  1. rewrite_data_files 操作はデータファイルの読み取りと書き直しを行うため、追加の I/O と計算負荷が発生します。クラスタリソースを適切に割り当ててください。
  2. 実行前に、データファイルの分布の確認の SQL を使って書き直しの必要性を評価できます。
  3. WHERE 条件で書き直すパーティションやデータ範囲を限定できます。この条件は、一致するデータを含まないファイルを除外し、書き直すファイル数とデータ量を減らします。
  4. 実行前に、書き直すファイルの選択ロジックの SQL で、書き直されるファイルを算出できます。

rewrite_manifests​

rewrite_manifests 操作はマニフェストファイルを書き直して Iceberg テーブルのメタデータを最適化し、クエリ性能の向上とメタデータの負荷軽減を図ります。

大規模な Iceberg テーブルでは小さなマニフェストファイルが多数あるとクエリ計画の性能に影響するため、この操作で最適化できます。

対応バージョン:4.1.0 以降

構文:

ALTER TABLE [catalog.][database.]table_name
EXECUTE rewrite_manifests();

パラメータ:

パラメータなし

戻り値:

rewrite_manifests 操作を実行すると、次の 2 カラムを持つ結果セットが返されます。

カラム名型説明
rewritten_manifests_countBIGINT書き直されたファイルの数
total_data_manifests_countBIGINT書き直されたデータマニフェストファイルの数

例:

ALTER TABLE iceberg_db.iceberg_table
EXECUTE rewrite_manifests();

rollback_to_snapshot​

rollback_to_snapshot 操作は、Iceberg テーブルを指定したスナップショットにロールバックします。

対応バージョン:4.0.2 以降

構文:

ALTER TABLE [catalog.][database.]table_name
EXECUTE rollback_to_snapshot ("snapshot_id" = "<snapshot_id>")

パラメータ:

パラメータ型必須説明
snapshot_idLongはいロールバック先のスナップショット ID

戻り値:

rollback_to_snapshot 操作を実行すると、次の 2 カラムを持つ結果セットが返されます。

カラム名型説明
previous_snapshot_idBIGINTロールバック前の現在のスナップショット ID
current_snapshot_idBIGINTロールバック後に現在のものとして設定されたスナップショット ID

例:

-- Roll back to snapshot 987654321
ALTER TABLE iceberg_db.iceberg_table
EXECUTE rollback_to_snapshot ("snapshot_id" = "987654321");

注意事項:

  1. この操作は WHERE 条件をサポートしません。
  2. 指定したスナップショットが存在しない場合、操作は失敗します。
  3. 現在のスナップショットがすでに対象のスナップショットである場合は、新しいスナップショットを作成せずに処理を終了します。

rollback_to_timestamp​

rollback_to_timestamp 操作は、Iceberg テーブルを指定した時点のスナップショットにロールバックします。

対応バージョン:4.0.2 以降

構文:

ALTER TABLE [catalog.][database.]table_name
EXECUTE rollback_to_timestamp ("timestamp" = "<timestamp>")

パラメータ:

パラメータ型必須説明
timestampStringはいロールバック先の時点。次の 2 形式に対応します。
1. ISO 日時形式:yyyy-MM-dd HH:mm:ss.SSS(例:2024-01-01 10:30:00.000)
2. ミリ秒のタイムスタンプ(例:1704067200000)

戻り値:

rollback_to_timestamp 操作を実行すると、次の 2 カラムを持つ結果セットが返されます。

カラム名型説明
previous_snapshot_idBIGINTロールバック前の現在のスナップショット ID
current_snapshot_idBIGINT指定した時点のスナップショット ID。現在のものとして設定されます。

例:

-- Roll back to specified point in time (ISO format)
ALTER TABLE iceberg_db.iceberg_table
EXECUTE rollback_to_timestamp ("timestamp" = "2024-01-01 10:30:00.000");

-- Roll back to specified point in time (timestamp format)
ALTER TABLE iceberg_db.iceberg_table
EXECUTE rollback_to_timestamp ("timestamp" = "1704067200000");

注意事項:

  1. この操作は WHERE 条件をサポートしません。
  2. timestamp パラメータは ISO 日時形式(yyyy-MM-dd HH:mm:ss.SSS)またはミリ秒のタイムスタンプ形式に対応します。
  3. 指定した時点に対応するスナップショットがない場合、操作は失敗します。

set_current_snapshot​

set_current_snapshot 操作は、Iceberg テーブルの現在のスナップショットを、指定したスナップショット ID または参照(Branch/Tag)に設定します。

対応バージョン:4.0.2 以降

構文:

ALTER TABLE [catalog.][database.]table_name
EXECUTE set_current_snapshot ("snapshot_id" = "<snapshot_id>" | "ref" = "<ref_name>")

パラメータ:

パラメータ型必須説明
snapshot_idLongいずれか一方現在のものとして設定するスナップショット ID
refStringいずれか一方現在のものとして設定する参照名(Branch または Tag)

戻り値:

set_current_snapshot 操作を実行すると、次の 2 カラムを持つ結果セットが返されます。

カラム名型説明
previous_snapshot_idBIGINT操作前の現在のスナップショット ID
current_snapshot_idBIGINT操作後のスナップショット ID(snapshot_id パラメータで指定した値、または ref パラメータから解決した値)

例:

-- Set current snapshot by snapshot ID
ALTER TABLE iceberg_db.iceberg_table
EXECUTE set_current_snapshot ("snapshot_id" = "123456789");

-- Set current snapshot by branch name
ALTER TABLE iceberg_db.iceberg_table
EXECUTE set_current_snapshot ("ref" = "feature_branch");

-- Set current snapshot by tag name
ALTER TABLE iceberg_db.iceberg_table
EXECUTE set_current_snapshot ("ref" = "v1.0");

注意事項:

  1. この操作は WHERE 条件をサポートしません。
  2. snapshot_id と ref パラメータは排他的であり、指定できるのはいずれか一方だけです。
  3. 指定したスナップショット ID または参照が存在しない場合、操作は失敗します。
  4. 現在のスナップショットがすでに対象のスナップショットである場合は、新しいスナップショットを作成せずに処理を終了します。

publish_changes​

publish_changes 操作は、WAP(Write-Audit-Publish)モードで、指定した wap.id を持つスナップショットを現在のテーブル状態として公開します。 指定した wap_id に一致する wap.id を持つスナップショットを探し、現在のテーブルに cherry-pick します。これにより、ステージング済みのデータがすべての読み取り操作から見えるようになります。

構文:

ALTER TABLE [catalog.][database.]table_name
EXECUTE publish_changes("wap_id" = "<wap_id>")

パラメータ:

パラメータ:

パラメータ名型必須説明
wap_idSTRINGはい公開する WAP スナップショット ID

戻り値:

publish_changes を実行すると、次の 2 カラムを持つ結果セットが返されます。

カラム名型説明
previous_snapshot_idSTRING公開操作前の現在のスナップショット ID(存在しない場合は NULL)
current_snapshot_idSTRING公開後に新しく作成され、現在のものとして設定されたスナップショット ID

例:

-- Publish the snapshot whose WAP ID is test_wap_001
ALTER TABLE iceberg_db.iceberg_table
EXECUTE publish_changes("wap_id" = "test_wap_001");

注意事項:

  1. この操作は WHERE 句および PARTITION/PARTITIONS 句をサポートしません。
  2. この操作が意味を持つのは、write.wap.enabled = true が設定され、wap.id を使用して WAP スナップショットが生成された Iceberg テーブルのみです。
  3. 指定した wap_id のスナップショットが見つからない場合、操作は失敗してエラーをスローします。
  4. 公開後は新しいスナップショットが現在のスナップショットになります。
  5. 公開前にスナップショットが存在しない場合、previous_snapshot_id は NULL になることがあります。

Iceberg テーブルの最適化​

データファイルの分布の確認​

次の SQL を使用して Iceberg テーブルのデータ分布と削除ファイル数を分析し、rewrite_data_files などの最適化が必要かどうかを判断できます。

  • データファイルのサイズ分布を表示します。小さなファイルが多すぎるかどうかを特定するのに役立ちます。

    SELECT
    CASE
    WHEN file_size_in_bytes BETWEEN 0 AND 8 * 1024 * 1024 THEN '0-8M'
    WHEN file_size_in_bytes BETWEEN 8 * 1024 * 1024 + 1 AND 32 * 1024 * 1024 THEN '8-32M'
    WHEN file_size_in_bytes BETWEEN 32 * 1024 * 1024 + 1 AND 128 * 1024 * 1024 THEN '32-128M'
    WHEN file_size_in_bytes BETWEEN 128 * 1024 * 1024 + 1 AND 512 * 1024 * 1024 THEN '128-512M'
    WHEN file_size_in_bytes > 512 * 1024 * 1024 THEN '> 512M'
    ELSE 'Unknown'
    END AS SizeRange,
    COUNT(*) AS FileNum
    FROM store_sales$data_files
    GROUP BY
    SizeRange;

    +-----------+---------+
    | SizeRange | FileNum |
    +-----------+---------+
    | 0-8M | 8 |
    | 8-32M | 6 |
    +-----------+---------+
  • データファイルと削除ファイルの数を表示します。

    SELECT
    CASE
    WHEN content = 0 THEN 'DataFile'
    WHEN content = 1 THEN 'PositionDeleteFile'
    WHEN content = 2 THEN 'EqualityDeleteFile'
    ELSE 'Unknown'
    END AS ContentType,
    COUNT(*) AS FileNum,
    SUM(file_size_in_bytes) AS SizeInBytes,
    SUM(record_count) AS Records
    FROM
    iceberg_table$files
    GROUP BY
    ContentType;

    +--------------------+---------+-------------+---------+
    | ContentType | FileNum | SizeInBytes | Records |
    +--------------------+---------+-------------+---------+
    | EqualityDeleteFile | 2787 | 1432518 | 27870 |
    | DataFile | 2787 | 4062416 | 38760 |
    | PositionDeleteFile | 11 | 36608 | 10890 |
    +--------------------+---------+-------------+---------+

Dangling Delete​

rewrite_data_files アクションの実行後、特定の Position Delete への参照が Snapshot メタデータから削除されずに残る場合があります(Dangling Delete)。この状態でメタデータの行数情報をそのまま使用すると、結果が正しくない可能性があります。

そのため、デフォルトでは COUNT(*) クエリで Position Delete ファイルが見つかった場合、COUNT のプッシュダウン最適化は有効になりません。代わりにファイルを直接読み取って実際の COUNT(*) 結果を取得します。ただし、この方法には時間がかかります。

Dangling Delete の問題がないことをユーザーが保証できる場合は、Doris のセッション変数 ignore_iceberg_dangling_delete を使用してこの確認を省略できます。この変数のデフォルトは false です。true にすると、システムはメタデータ内の行数情報に基づいて COUNT(*) の結果を直接返し、クエリ効率を高めます。

この機能はバージョン 3.1.4 と 4.0.3 以降でサポートされます。

付録​

rewrite_data_files のファイル選択戦略​

このセクションでは、書き直すファイルを選択するロジックを説明します。次の SQL クエリを使用し、システムテーブルの情報に基づいて、どのファイルが書き直されるかを分析することもできます。これにより、実際の書き直し操作を実行する前に、その動作を調査して理解できます。

書き直し操作では、2 段階のフィルタリングとグループ化を行います。

  1. 第 1 段階:ファイル単位のフィルタリング

    まず、ファイル単位の条件に基づいてフィルタリングします。次のいずれかの条件を満たすファイルのみが書き直し候補になります。

    1. ファイルサイズが範囲外:ファイルが min-file-size-bytes より小さいか、max-file-size-bytes より大きい場合。
    2. 削除ファイルが多すぎる:関連する削除ファイル数が delete-file-threshold 以上の場合。
    3. 削除率が高い:削除されたレコードの割合が delete-ratio-threshold 以上の場合。

    削除ファイルに関する条件の注意点: 削除ファイルに関する条件(delete-file-threshold と delete-ratio-threshold)は書き直すファイルの選択に影響しますが、システムテーブルの SQL クエリでは正確に算出できません。現在のシステムテーブルの情報だけでは、削除ファイルがどのデータファイルに影響するかを正確に判断できないためです。削除ファイルは特定のデータファイルだけに影響する場合があり、特に Position Delete ファイルでは、削除ファイルとデータファイルの対応関係を知るために、現在のシステムテーブルでは利用できない詳細なメタデータが必要です。実際の書き直し操作では、システムテーブルに公開されていない詳細なメタデータに基づいてこれらの条件を評価します。

  2. 第 2 段階:BinPack によるグループ化とグループ単位のフィルタリング

    ファイル単位のフィルタリング後、ファイルをパーティション別に分け、各パーティション内でファイルサイズと max-file-group-size-bytes に基づく BinPack アルゴリズムでグループ化します。BinPack アルゴリズムは、書き直し操作を最適化するため、ファイルを適切にグループへ詰め込みます。

    グループ化後、グループ単位の条件でファイルグループをフィルタリングします。次のいずれかの条件を満たすファイルグループを書き直します。

    1. 入力ファイルが十分にある:グループ内のファイル数が 1 を超え、かつ min-input-files 以上である場合。
    2. 内容量が十分にある:グループ内のファイル数が 1 を超え、かつ合計サイズが target-file-size-bytes を超える場合。
    3. 内容量が多すぎる:グループの合計サイズが max-file-group-size-bytes を超える場合。
    4. 削除ファイルに関する問題があるファイルを含む:グループ内の少なくとも一つのファイルで、削除ファイルが多すぎるか、削除率が高い場合。

    BinPack によるグループ化の注意点: 各パーティション内でファイルをグループ化する BinPack アルゴリズムは複雑な最適化アルゴリズムであり、システムテーブルの SQL クエリでは正確に再現できません。このアルゴリズムはファイルサイズと max-file-group-size-bytes を考慮してファイルをグループに詰め込むため、単純なパーティション単位のグループ化とは異なる結果になる可能性があります。したがって、以下の SQL クエリで特定できるのはファイル単位の条件を満たすファイルのみで、最終的に書き直されるファイルグループを正確に算出することはできません。

クエリ戦略の例を以下に示します。

  • クエリ 1:ファイル単位の条件を満たすファイルを特定

    このクエリは、ファイル単位の条件(ファイルサイズ)を満たし、書き直し候補となるファイルを特定します。

    -- Set parameters (adjust according to your rewrite parameters)
    SET @min_file_size_bytes = 16 * 1024 * 1024; -- 16 MB (default: target-file-size-bytes * 0.75)
    SET @max_file_size_bytes = 768 * 1024 * 1024; -- 768 MB (default: target-file-size-bytes * 1.8)

    SELECT
    file_path,
    `partition`,
    file_size_in_bytes / 1024.0 / 1024.0 AS file_size_mb,
    record_count,
    CASE
    WHEN file_size_in_bytes < @min_file_size_bytes THEN 'Too small'
    WHEN file_size_in_bytes > @max_file_size_bytes THEN 'Too large'
    END AS size_issue
    FROM iceberg_table$data_files
    WHERE file_size_in_bytes < @min_file_size_bytes
    OR file_size_in_bytes > @max_file_size_bytes
    ORDER BY `partition`, file_size_in_bytes DESC;

    出力例:

    +----------------------------------------------------------------------------------------+---------------------------+-------------+--------------+------------+
    | file_path | partition | file_size_mb | record_count | size_issue |
    +----------------------------------------------------------------------------------------+---------------------------+-------------+--------------+------------+
    | s3a://bucket/path/to/table/data/date_col=2024-01-01/00000-0-00000-00000-0.parquet | {"date_col":"2024-01-01"} | 0.00215 | 5 | Too small |
    | s3a://bucket/path/to/table/data/date_col=2024-01-01/00001-0-00001-00001-0.parquet | {"date_col":"2024-01-01"} | 0.00198 | 5 | Too small |
    | s3a://bucket/path/to/table/data/date_col=2024-01-02/00002-0-00002-00002-0.parquet | {"date_col":"2024-01-02"} | 0.00231 | 5 | Too small |
    | s3a://bucket/path/to/table/data/date_col=2024-01-02/00003-0-00003-00003-0.parquet | {"date_col":"2024-01-02"} | 850.23456 | 1250000 | Too large |
    | s3a://bucket/path/to/table/data/date_col=2024-01-03/00004-0-00004-00004-0.parquet | {"date_col":"2024-01-03"} | 0.00245 | 5 | Too small |
    +----------------------------------------------------------------------------------------+---------------------------+-------------+--------------+------------+
    5 rows in set

    注: このクエリで特定できるのは、ファイル単位の条件(ファイルサイズ)を満たすファイルだけです。実際に書き直されるファイルグループは BinPack によるグループ化に依存し、SQL クエリで正確に再現することはできません。このクエリで特定されたファイルが BinPack アルゴリズムによって別の形でグループ化され、グループ単位の条件で一部のグループが除外される場合があります。

  • クエリ 2:全体の統計の集計

    このクエリは、ファイル単位の条件を満たすファイルの全体的な統計を示します。

    -- Set parameters (adjust according to your rewrite parameters)
    SET @min_file_size_bytes = 16 * 1024 * 1024;
    SET @max_file_size_bytes = 768 * 1024 * 1024;

    WITH file_analysis AS (
    SELECT
    `partition`,
    file_path,
    file_size_in_bytes,
    record_count,
    (file_size_in_bytes < @min_file_size_bytes OR file_size_in_bytes > @max_file_size_bytes) AS meets_file_level_conditions
    FROM iceberg_table$data_files
    )
    SELECT
    'Total files' AS metric,
    COUNT(*) AS value
    FROM file_analysis
    UNION ALL
    SELECT
    'Files meeting file-level conditions',
    SUM(CASE WHEN meets_file_level_conditions THEN 1 ELSE 0 END)
    FROM file_analysis
    UNION ALL
    SELECT
    'Total size (GB)',
    ROUND(SUM(file_size_in_bytes) / 1024.0 / 1024.0 / 1024.0, 2)
    FROM file_analysis
    UNION ALL
    SELECT
    'Size meeting file-level conditions (GB)',
    ROUND(SUM(CASE WHEN meets_file_level_conditions THEN file_size_in_bytes ELSE 0 END) / 1024.0 / 1024.0 / 1024.0, 2)
    FROM file_analysis
    UNION ALL
    SELECT
    'Percentage meeting file-level conditions (%)',
    ROUND(SUM(CASE WHEN meets_file_level_conditions THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2)
    FROM file_analysis;

    出力例:

    +----------------------------------------------+--------+
    | metric | value |
    +----------------------------------------------+--------+
    | Total files | 15.00 |
    | Total size (GB) | 2.45 |
    | Files meeting file-level conditions | 12.00 |
    | Size meeting file-level conditions (GB) | 1.85 |
    | Percentage meeting file-level conditions (%) | 80.00 |
    +----------------------------------------------+--------+
    5 rows in set

    注意事項:

    • 例の iceberg_table を実際のテーブル名に置き換えてください。
    • 実際の書き直しパラメータに合わせて、パラメータ値(@min_file_size_bytes、@max_file_size_bytes)を調整してください。
    • 上記のデフォルト値は、書き直しパラメータのデフォルト(min-file-size-bytes = target-file-size-bytes * 0.75、max-file-size-bytes = target-file-size-bytes * 1.8)に対応します。
  • スナップショットと Branch の関係を表示:

    SELECT
    refs_data.snapshot_id,
    snapshots.committed_at,
    snapshots.operation,
    ARRAY_SORT(refs_data.refs)
    FROM (
    SELECT
    snapshot_id,
    ARRAY_AGG(CONCAT(type, ':', name)) AS refs
    FROM
    iceberg_table$refs
    GROUP BY
    snapshot_id
    ) AS refs_data
    JOIN (
    SELECT
    snapshot_id,
    committed_at,
    operation
    FROM
    iceberg_table$snapshots
    ) AS snapshots
    ON refs_data.snapshot_id = snapshots.snapshot_id
    ORDER BY
    snapshots.committed_at;

    +---------------------+----------------------------+-----------+-------------------------------------+
    | snapshot_id | committed_at | operation | ARRAY_SORT(refs_data.refs) |
    +---------------------+----------------------------+-----------+-------------------------------------+
    | 8272911997874079853 | 2025-07-10 15:27:07.177000 | append | ["BRANCH:b1", "TAG:t1"] |
    | 1325777059626757917 | 2025-07-10 15:27:07.530000 | append | ["BRANCH:b2", "TAG:t2"] |
    | 76492482642020578 | 2025-07-10 15:27:07.865000 | append | ["BRANCH:b3", "TAG:t3"] |
    | 1788715857849070138 | 2025-07-12 04:15:19.626000 | append | ["BRANCH:main", "TAG:t4", "TAG:t5"] |
    +---------------------+----------------------------+-----------+-------------------------------------+
On This Page