AnalyticDB for MySQL (AnalyticDB) の XIHE エンジンは、Apache Iceberg のデータレイクテーブル形式をネイティブにサポートしています。標準 SQL を使用して Iceberg テーブルを作成し、データの書き込み、クエリ、スキーマ変更を実行できます。このトピックでは、XIHE SQL を使用して Iceberg テーブルを読み書きする方法について説明します。
前提条件
クラスターのエディションが Enterprise Edition、Basic Edition、または Data Lakehouse Edition であること。
クラスターのカーネルバージョンが 3.2.3.0 以降であること。
外部データベースが作成されていること。詳細については、「CREATE EXTERNAL DATABASE」をご参照ください。
内部レイク モード (AnalyticDB が管理するレイクストレージ) を使用するには、チケットを提出してレイクストレージ機能を有効にする必要があります。詳細については、「レイクストレージ」をご参照ください。
背景情報
Apache Iceberg は、ACID トランザクション、スキーマエボリューション、パーティション変換などの機能をサポートするオープンなデータレイクテーブル形式です。データは OSS 上に Parquet 形式で保存され、Iceberg と互換性のある任意のコンピューティングエンジンがデータを直接読み取ることができます。
AnalyticDB は 2 つのストレージモードをサポートしています。ストレージモードはテーブル作成時に決定され、後から変更できません。
ディメンション | 内部レイク (マネージドレイクストレージ) | 外部レイク (ユーザー所有の OSS) |
ストレージ管理 | AnalyticDB によるフルマネージド | ユーザー管理の OSS バケット |
テーブル作成時の主要パラメータ |
|
|
有効化の方法 | チケットを提出して有効化を申請 | 追加の有効化は不要。認可のみ必要 |
適用シナリオ | O&M の簡素化が必要な新規プロジェクト | 既存の OSS データがある場合、または自己管理ストレージが必要な場合 |
テーブルの作成
構文
CREATE TABLE [IF NOT EXISTS] <db>.<table> (
<col1> <type1> [COMMENT '<comment>'],
<col2> <type2> [COMMENT '<comment>'],
...
)
[COMMENT '<table_comment>']
[PARTITIONED BY (<partition_expr1>[, <partition_expr2>, ...])]
STORED AS ICEBERG
[LOCATION '<oss_path>']
[TBLPROPERTIES (
'<key1>' = '<value1>',
...
)];句 | 必須 | 説明 |
| はい | テーブル形式を Iceberg として宣言します。 |
| いいえ | パーティション式。ID パーティショニング (列値を直接使用) と変換関数パーティショニング ( |
| 外部レイクに必須 | ユーザー所有の OSS パスを指します。形式は |
| 内部レイクに必須 | 内部レイクモードでは、 |
TBLPROPERTIES では、以下のテーブルプロパティを設定できます。
プロパティ | デフォルト値 | 説明 |
| N/A | 内部レイクモードで必須です。値を |
| N/A | 内部レイクモードに必須です。値を AnalyticDB によって割り当てられた OSS バケットの名前に設定します。 |
|
| Iceberg フォーマットのバージョン。 |
| N/A | 外部レイクモードで既存の Iceberg データを参照するには、 |
| N/A | 行レベルの DELETE 用の識別子列 (主キーと同様) です。形式は |
外部レイクテーブルの例
-- データベースの作成
CREATE DATABASE IF NOT EXISTS lake_db;
-- 外部レイクの Iceberg テーブルを作成
CREATE TABLE lake_db.orders (
order_id BIGINT COMMENT '注文 ID',
user_id BIGINT COMMENT 'ユーザー ID',
status STRING COMMENT '注文ステータス',
total_amount DECIMAL(18, 2) COMMENT '注文金額',
created_at TIMESTAMP COMMENT '注文日時',
dt DATE COMMENT 'パーティション日付'
)
COMMENT '注文テーブル'
PARTITIONED BY (dt)
STORED AS ICEBERG
LOCATION 'oss://<your-bucket>/warehouse/lake_db/orders/';外部レイクモードでは、エンジンは指定された OSS パスにディレクトリとメタデータファイルを自動的に作成します。事前に OSS ディレクトリを作成する必要はありません。
内部レイクテーブルの例
CREATE TABLE lake_db.orders (
order_id BIGINT COMMENT '注文 ID',
user_id BIGINT COMMENT 'ユーザー ID',
status STRING COMMENT '注文ステータス',
total_amount DECIMAL(18, 2) COMMENT '注文金額',
created_at TIMESTAMP COMMENT '注文日時',
dt DATE COMMENT 'パーティション日付'
)
COMMENT '注文テーブル'
PARTITIONED BY (dt)
STORED AS ICEBERG
TBLPROPERTIES (
'catalog_type' = 'ADB',
'adb_lake_bucket' = 'adb-lake-cn-<region>-xxxx'
);内部レイクテーブルを作成する場合、LOCATION を指定する必要はありません。ストレージパスは AnalyticDB によって自動的に割り当てられます。コンソールのレイクストレージページで adb_lake_bucket の値を確認できます。
CTAS (CREATE TABLE AS SELECT)
CTAS は、テーブルを作成すると同時にクエリ結果を書き込みます。列名と型は SELECT 文から推論されます。
CREATE TABLE lake_db.orders_copy
PARTITIONED BY (dt)
STORED AS ICEBERG
LOCATION 'oss://<your-bucket>/warehouse/lake_db/orders_copy/'
AS SELECT * FROM lake_db.orders;パーティション変換関数
Identity パーティショニング (列の値を直接使用) に加えて、Iceberg は既存の列に基づく変換関数パーティショニングをサポートしています。書き込み時にパーティション値を指定する必要はありません。エンジンは列の値に基づいてデータを自動的にルーティングします。
関数 | 適用可能な型 | 例 |
identity | 任意 |
|
| DATE / TIMESTAMP |
|
| DATE / TIMESTAMP |
|
| DATE / TIMESTAMP |
|
| TIMESTAMP |
|
day(created_at) でパーティショニングする場合、別の dt 列を維持する必要はありません。 Iceberg は、created_at からパーティショニング用の日付を自動的に抽出します:
CREATE TABLE lake_db.orders_by_day (
order_id BIGINT,
user_id BIGINT,
status STRING,
total_amount DECIMAL(18, 2),
created_at TIMESTAMP
)
PARTITIONED BY (day(created_at))
STORED AS ICEBERG
LOCATION 'oss://<your-bucket>/warehouse/lake_db/orders_by_day/';その他の DDL 操作
-- 完全な CREATE TABLE 文を表示
SHOW CREATE TABLE lake_db.orders;
-- 列構造を表示
DESCRIBE lake_db.orders;
-- テーブルを削除
DROP TABLE IF EXISTS lake_db.orders;内部レイクテーブルで DROP TABLE を実行すると、OSS 上のデータファイルとメタデータの両方が完全に削除されます。この操作は元に戻すことはできません。外部レイクテーブルでの DROP TABLE の動作は、ストレージパスの所有権設定によって異なります。
データの書き込み
INSERT INTO (追記)
INSERT INTO lake_db.orders
SELECT * FROM VALUES
(1001, 501, 'paid', 299.90, TIMESTAMP '2026-06-11 10:00:00', DATE '2026-06-11'),
(1002, 502, 'pending', 158.00, TIMESTAMP '2026-06-11 10:05:00', DATE '2026-06-11'),
(1003, 503, 'shipped', 450.00, TIMESTAMP '2026-06-11 10:10:00', DATE '2026-06-12')
AS t(order_id, user_id, status, total_amount, created_at, dt);INSERT 構文では、INSERT INTO t SELECT * FROM VALUES (...) 形式を使用する必要があります。INSERT INTO t VALUES (...) を直接使用するとエラーになります。
INSERT OVERWRITE (上書き)
パーティション分割されたテーブルに対して INSERT OVERWRITE を実行すると、Iceberg は動的パーティション上書き戦略を使用します。SELECT 結果に含まれるパーティションのみが上書きされ、他のパーティションのデータは影響を受けません。
-- dt='2026-06-11' パーティションのデータのみを上書きします。他のパーティションは影響を受けません。
INSERT OVERWRITE lake_db.orders
SELECT * FROM VALUES
(2001, 601, 'paid', 999.00, TIMESTAMP '2026-06-11 12:00:00', DATE '2026-06-11')
AS t(order_id, user_id, status, total_amount, created_at, dt);DELETE (行レベル削除)
Iceberg テーブルは、条件に基づく行レベル削除をサポートしています。DELETE を使用するには、以下の条件を満たす必要があります:
テーブルの作成時に、
format_versionは'3'に設定されます。identifier-fields(識別子列、主キーと同様) は、テーブルの作成時に TBLPROPERTIES で指定されます。
-- テーブルの作成:format-version=3 と identifier-fields を指定
CREATE TABLE lake_db.orders_v3 (
order_id BIGINT,
user_id BIGINT,
status STRING,
total_amount DECIMAL(18, 2),
created_at TIMESTAMP
)
PARTITIONED BY (day(created_at))
STORED AS ICEBERG
LOCATION 'oss://<your-bucket>/warehouse/lake_db/orders_v3/'
TBLPROPERTIES (
'format-version' = '3',
'identifier-fields' = '[order_id]'
);
-- 条件に一致する行を削除
DELETE FROM lake_db.orders_v3 WHERE status = 'cancelled';データのクエリ
基本的なクエリ
SELECT * FROM lake_db.orders WHERE dt = DATE '2026-06-11';
SELECT dt, COUNT(*) AS cnt, SUM(total_amount) AS total
FROM lake_db.orders
GROUP BY dt;パーティションプルーニング
WHERE 句にパーティション列またはパーティション変換関数が含まれる場合、エンジンは自動的にパーティションプルーニングを実行し、関連するパーティションのデータファイルのみをスキャンします。
-- Identity パーティショニング:パーティション列に直接一致させる
SELECT * FROM lake_db.orders WHERE dt = DATE '2026-06-11';
-- day(col) パーティショニング:時間範囲に一致させる
SELECT * FROM lake_db.orders_by_day
WHERE created_at >= TIMESTAMP '2026-06-11 00:00:00'
AND created_at < TIMESTAMP '2026-06-12 00:00:00';述語プッシュダウン
Iceberg は WHERE 句の述語をデータファイルレベルにプッシュダウンし、Parquet ファイル内の統計情報 (最小/最大/NULL カウント) を使用して、条件を満たさない行グループを除外します。これにより、実際に読み取られるデータ量が削減されます。等価 (=)、範囲 (<、>、BETWEEN)、IN などの述語をサポートしています。
テーブルスキーマの変更
列の追加
ALTER TABLE lake_db.orders ADD COLUMNS (
region STRING COMMENT '注文地域'
);
-- 検証
DESCRIBE lake_db.orders;新しい列は列リストの末尾に追加されます。既存の行の場合、新しい列の値は NULL です。
新しい列は NULL 許容である必要があります。NOT NULL 列の追加はサポートされていません。スキーマの変更は metadata.json のスキーマ定義のみを変更し、既存のデータファイルは書き換えません。
型の昇格
安全な型の昇格 (例: INT から BIGINT) がサポートされています。
ALTER TABLE lake_db.orders CHANGE COLUMN order_id order_id BIGINT;設定パラメータ
以下の設定パラメータは、Config または Hint を使用して設定でき、Iceberg テーブルの書き込みおよびクエリの動作を調整します。
パラメータ | 説明 | 再起動の要否 |
| 書き込み時にライターごとに許可される最大パーティション数です。デフォルト値は 100 です。 | いいえ |
| メタデータキャッシュを有効にするかどうかを指定します。デフォルト値は true です。 | いいえ |
| クエリのマニフェストキャッシュ戦略。有効な値は | いいえ |
以下のパラメータはインスタンスレベルのパラメータです。変更を有効にするには、インスタンスを再起動する必要があります。
パラメータ | 説明 | デフォルト値 |
| マニフェストファイルキャッシュのマスタースイッチです。 | false |
| マニフェストキャッシュの最大合計バイト数です。 | 104857600 (100 MB) |
| キャッシュエントリの有効期限 (ミリ秒単位) です。 | 0 (無期限) |
| キャッシュ可能な単一マニフェストファイルの最大バイト数です。この制限を超えるファイルはキャッシュされません。 | 8388608 (8 MB) |
制限事項
文字列型には
STRINGを使用します。VARCHARとCHAR(N)はサポートされていません。STORED AS ICEBERGは必須の句です。この句を省略した場合、テーブルは Iceberg テーブルとして作成されません。format_version='2'(デフォルト) と'3'の両方がサポートされています。行レベルの DELETE には'3'が必要です。INSERT 構文は、
INSERT INTO t SELECT * FROM VALUES (...)形式を使用する必要があります。INSERT INTO t VALUES (...)形式はサポートされていません。INSERT OVERWRITE は、パーティション分割されたテーブルに対して動的パーティション上書き戦略を使用します。SELECT 結果に含まれるパーティションのみが置き換えられます。
行レベルの DELETE には
format_version='3'とidentifier-fieldsが必要です。ALTER TABLE ADD COLUMNS で追加される列は NULL 許容である必要があります。
ストレージモード (内部レイクまたは外部レイク) は、テーブル作成後に変更できません。
パーティションが多すぎると、パフォーマンスに影響する可能性があります。高カーディナリティ列については、
day()またはmonth()を使用してパーティションの数を制御することをお勧めします。