全部產品
Search
文件中心

AnalyticDB:Iceberg外表(XIHE SQL)

更新時間:Jul 07, 2026

AnalyticDB for MySQL的XIHE引擎原生支援Apache Iceberg湖表格式。您可以通過標準SQL建立Iceberg表,並執行資料寫入和查詢操作。本文介紹Iceberg外表(XIHE SQL)的方法。

前提條件

  • 叢集的產品系列為企業版、基礎版或湖倉版。

  • 叢集的核心版本為3.2.3.0及以上版本。

  • 已建立外部資料庫。建立方法請參見CREATE EXTERNAL DATABASE

  • 如需使用內湖模式(AnalyticDB託管湖儲存),需提交工單開通湖儲存功能。詳情請參見湖儲存

背景資訊

Apache Iceberg是一種開放的資料湖表格式,支援ACID事務、分區裁剪等特性。資料以Parquet格式儲存在OSS上,任何相容Iceberg的計算引擎均可直接讀取。

AnalyticDB支援兩種儲存模式,在建表時一次性確定,建表後不可變更:

維度

內湖(託管湖儲存)

外湖(使用者自有OSS)

儲存管理

AnalyticDB全託管

使用者自管理OSS Bucket

建表關鍵參數

catalog_type='ADB' + adb_lake_bucket

LOCATION 'oss://...'

開通方式

需提交工單申請開通

同帳號下無需額外操作

適用情境

新專案,希望簡化營運

已有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 (
    'format-version'    = '<2|3>',                 -- 預設2
    'catalog_type'      = 'ADB',                   -- 內湖必填
    'adb_lake_bucket'   = '<bucket_name>',          -- 內湖必填
    ...
)];

子句

是否必填

說明

STORED AS ICEBERG

聲明表格式為Iceberg。

PARTITIONED BY (...)

分區運算式。支援identity分區(直接使用列值)和轉換函式分區(yearmonthdayhour)。

LOCATION

外湖必填

指向使用者自有OSS路徑,格式為oss://<bucket>/<path>/。路徑建議以/<database>/<table>/結尾。

TBLPROPERTIES

內湖必填

內湖模式需包含catalog_type='ADB'adb_lake_bucket='...'

TBLPROPERTIES中可配置的表屬性如下:

屬性

預設值

說明

catalog_type

內湖必填,取值為'ADB'

adb_lake_bucket

內湖必填,取值為AnalyticDB分配的OSS Bucket名。

format_version

'2'

Iceberg Format Version,支援'2'(預設)和'3'

metadata_location

外湖模式下,如需指向已有Iceberg資料,需填寫metadata.json的OSS路徑。

外湖建表示例

-- 建立資料庫
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 '下單時間'
)
COMMENT '訂單主表'
PARTITIONED BY (dt DATE)
STORED AS ICEBERG
LOCATION 'oss://<YOUR-BUCKET>/warehouse/lake_db/orders/';
說明

外湖建表通過LOCATION指定路徑,不寫catalog_typeLOCATION路徑建議以/<database>/<table>/結尾,例如oss://<YOUR-BUCKET>/warehouse/lake_db/orders/

內湖建表示例

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 '下單時間'
)
COMMENT '訂單主表'
PARTITIONED BY (dt DATE)
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 DATE)
STORED AS ICEBERG
LOCATION 'oss://<YOUR-BUCKET>/warehouse/lake_db/orders_copy/'
AS SELECT * FROM lake_db.orders;

分區管理

Iceberg的分區與傳統Hive分區有本質區別:

維度

Hive分區

Iceberg分區

分區是否為列

分區列是獨立列

分區可以基於現有列的轉換(如day(dt)),不額外占列

寫入時需感知分區

INSERT必須指定分區值

INSERT不需要顯式寫分區值,引擎自動路由

查詢時需感知分區

必須WHERE帶分區列

引擎自動進行分區裁剪

Iceberg支援identity分區(直接使用列值)和基於現有列的轉換函式分區。寫入時無需指定分區值,引擎根據列值自動路由。

函數

適用類型

樣本

identity

任意

PARTITIONED BY (dt DATE)

year

DATE / TIMESTAMP

PARTITIONED BY (year(dt))

month

DATE / TIMESTAMP

PARTITIONED BY (month(dt))

day

DATE / TIMESTAMP

PARTITIONED BY (day(created_at))

hour

TIMESTAMP

PARTITIONED BY (hour(created_at))

說明

分區轉換不是獨立列:day(created_at)不會建立新列,Iceberg在Manifest檔案中記錄轉換後的分區值。分區過多會影響效能,高基數列建議使用day()month()控制分區數。

使用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操作

-- 查看錶的完整建表語句
SHOW CREATE TABLE lake_db.orders;

-- 查看列結構
DESCRIBE lake_db.orders;

-- 刪除表
DROP TABLE IF EXISTS lake_db.orders;

-- 刪除資料庫(庫內不能有表,否則報錯)
DROP DATABASE IF EXISTS lake_db;
警告

對內湖表執行DROP TABLE會同時刪除OSS上的資料檔案和中繼資料,操作無法復原。外湖表的DROP TABLE僅刪除AnalyticDB中的表定義,OSS上的資料檔案不受影響。

寫入資料

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);
說明

核心版本3.2.8之前,INSERT文法必須使用INSERT INTO ... SELECT * FROM VALUES (...) AS t(...)形式。3.2.8及以上版本支援INSERT INTO ... 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 FROM lake_db.orders 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檔案內部的統計資訊(min/max/null count)過濾不滿足條件的row group,減少實際讀取的資料量。

謂詞下推生效條件:

  • WHERE條件中的列存在統計資訊。

  • 謂詞為簡單比較(=<><=>=INBETWEEN)。

  • 列類型與統計資訊類型匹配。

-- 謂詞下推生效:order_id有min/max統計資訊
SELECT * FROM lake_db.orders
WHERE order_id = 1001;

-- 範圍謂詞下推
SELECT * FROM lake_db.orders
WHERE total_amount BETWEEN 100 AND 500;

查詢注意事項

  • 分區裁剪僅對WHERE條件中直接引用分區列或分區轉換函式的情境生效。

  • 複雜謂詞(如函數調用、OR條件)可能影響謂詞下推效果。

  • 跨Iceberg表JOIN效能取決於資料量和分區設計。

可選配置項

以下配置項可通過Config或Hint方式設定,用於調整Iceberg表的寫入和查詢行為。

配置名稱

說明

是否需要重啟

iceberg_write_max_partition

寫入時每個Writer允許的最大分區數。預設值100。

iceberg_metadata_cache_enabled

中繼資料快取開關。預設值true。

iceberg_manifest_cache_query_strategy

查詢時Manifest緩衝策略。取值:none(預設,正常使用緩衝)、bypass(跳過緩衝)、clear(清除緩衝後讀取)、reload(清除後重新緩衝)。

以下為執行個體級配置,修改後需要重啟執行個體生效:

配置名稱

說明

預設值

ICEBERG_IO_MANIFEST_CACHE_ENABLED

Manifest檔案快取總開關。

false

ICEBERG_IO_MANIFEST_CACHE_MAX_TOTAL_BYTES

Manifest緩衝最大總位元組數。

104857600(100 MB)

ICEBERG_IO_MANIFEST_CACHE_EXPIRATION_INTERVAL_MS

緩衝條目到期時間(毫秒)。

0(永不到期)

ICEBERG_IO_MANIFEST_CACHE_MAX_CONTENT_LENGTH

單個Manifest檔案可快取的最大位元組數,超過則不緩衝。

8388608(8 MB)

使用限制

  • 字串類型統一使用STRING,不支援VARCHARCHAR(N)

  • STORED AS ICEBERG是必需子句,缺失時不會建立Iceberg表。

  • 核心版本3.2.8之前,INSERT文法必須使用INSERT INTO t SELECT * FROM VALUES (...)形式。3.2.8及以上版本支援INSERT INTO t VALUES (...)直接寫法。

  • INSERT OVERWRITE對分區表採用動態分區覆寫策略,僅替換SELECT結果中涉及的分區。

  • 儲存模式(內湖/外湖)建表後不可變更。

  • 內湖建表必須同時指定catalog_type='ADB'adb_lake_bucket,缺一不可。外湖建表通過LOCATION指定路徑,不寫catalog_type

  • 分區過多會影響效能,高基數列建議使用day()month()控制分區數。