🧊

HiveテーブルをIcebergテーブルに移行するプロシージャの実装

に公開

migrateプロシージャのシンタックス

Trinoバージョン411でIcebergコネクタに追加されたmigrateプロシージャについて解説します。このプロシージャは、既存のHiveテーブル(ORC、Parquet、Avroフォーマット)をIcebergテーブルに変換します。

CALL iceberg.system.migrate(
 schema_name => 'testdb', 
 table_name => 'customer_orders', 
 recursive_directory => 'true');

このプロシージャは3つの引数をサポートしています。

名前 必須 説明
schema_name Required スキーマ名
table_name Required テーブル名
recursive_directory Optional ディレクトリを再帰的に走査するか

recursive_directoryの設定可能な値はtrue、false、failです。

  • true: ディレクトリを再帰的に検索する
  • false: 直下のディレクトリのファイルのみを検索する
  • fail: テーブルまたはパーティションのロケーション配下にネストされたディレクトリが存在する場合に例外をスローします。failがデフォルトです。

migrateプロシージャの実装

次に、このプロシージャの実装の詳細について説明します。

1. Hiveテーブルの定義に基づいてIcebergのスキーマオブジェクトを生成する

引数で指定されたテーブルをHive Metastore (HMS)やGlueから取得します。
Hiveテーブルの情報からIcebergを作成するのに必要なSchemaPartitionSpecのオブジェクトを生成します。

2. Hiveテーブルのファイルをリストする

非パーティションテーブルであればテーブルのパス、パーティションテーブルであれば各パーティションのディレクトリ配下を見ていきます。
ParquetやORCファイルはフッターからMetrics(行数、カラム毎のサイズ、非NULLの数、NULLの数、NaNの数、上限と下限)を算出します。Avroでは行数のみ算出します。

次に既存のHiveのデータファイルからDataFileのオブジェクトを生成します。Trinoでは以下のようなヘルパーメソッドを使っています。

    public static DataFile buildDataFile(String path, long length, Optional<StructLike> partition, PartitionSpec spec, String format, Metrics metrics)
    {
        DataFiles.Builder dataFile = DataFiles.builder(spec)
                .withPath(path)
                .withFormat(format)
                .withFileSizeInBytes(length)
                .withMetrics(metrics);
        partition.ifPresent(dataFile::withPartition);
        return dataFile.build();
    }

3. トランザクションを開始する

Icebergテーブルを新規作成するTransactionを作成し、前のステップで生成したDataFileのリストを追加していきます。この時点で、Icebergのメタデータファイルは生成されていますが、メタストア上ではまだHiveテーブルのままです。

Table table = transaction.table();
AppendFiles append = table.newAppend();
dataFiles.forEach(append::appendFile);
append.commit();

4. メタストアの情報を更新する

Trinoやその他のクエリエンジンはメタストア上の情報を見てそのテーブルフォーマットを判断しています。このステップでtable_typeテーブルプロパティにICEBERGを設定し、メタストアの情報を更新します。

逆に言い換えるとIcebergテーブルを元に戻したい場合はtable_typeプロパティを削除してしまえば、Hiveテーブルとしてアクセス可能です。

5. トランザクションをコミットする

最後にトランザクションをコミットします。このコミットでIcebergのアーキテクチャでよく出てくる”最新のメタデータファイルへのポインタ”となるmetadata_locationテーブルプロパティが設定され、Icebergテーブルへのアクセスが可能となります。

Discussion