Iceberg表的操作 - 创建数据库和表

让我们在Iceberg Catalog中创建第一个数据库:

%%sql
CREATE DATABASE IF NOT EXISTS ${ICEBERG_DB}

执行完成后刷新glue的页面,会发现一个新的database被创建出来:

image-20250312205900185

创建数据库后,我们可以开始使用原始客户表中的数据创建表。我们将使用此表探索Iceberg的基本功能。

%%sql
CREATE TABLE ${ICEBERG_DB}.${ICEBERG_CUSTOMER_TABLE} (
    c_customer_sk INT COMMENT '唯一ID', 
    c_customer_id STRING, 
    c_first_name STRING, 
    c_last_name STRING, 
    c_email_address STRING
) USING iceberg
TBLPROPERTIES (
    'format-version'='2'
)
COMMENT '此表包含客户数据'
  • 这里使用 USING iceberg 表示创建的表将采用 Iceberg 表格式进行存储和管理,而不是默认的 Spark 内部表格式或其他格式(如 Parquet、ORC、Delta 等)。
  • format-version='2':指定使用 Iceberg 格式版本 2,这是较新的版本

执行完成后,在glue里可以找到新的table:

image-20250312210455936

使用以下命令验证数据库中的新表,但请注意,目前表中没有数据。

%%sql
SHOW TABLES IN ${ICEBERG_DB}

image-20250312210121287

使用DESCRIBE查询检查详细的表信息。

%%sql
DESCRIBE TABLE EXTENDED ${ICEBERG_DB}.${ICEBERG_CUSTOMER_TABLE}

image-20250312210144613

使用SHOW TBLPROPERTIES检查表属性。

%%sql
SHOW TBLPROPERTIES ${ICEBERG_DB}.${ICEBERG_CUSTOMER_TABLE}

image-20250312210159626

Iceberg表结构

下图解释了Iceberg 的架构,主要分为三层:

顶层 - Iceberg Catalog (目录层)

  • 顶部是 Iceberg Catalog,包含了 db1.table1 的引用, “current metadata pointer”(当前元数据指针),指向最新的有效元数据文件

中间层 - Metadata Layer (元数据层)

  • 包含元数据文件(metadata file),每个元数据文件可以有多个快照(snapshots,图中的s0、s1)
  • 每个快照(snapshot)链接到一个清单列表(manifest list)
  • 清单列表(manifest list)进一步链接到多个清单文件(manifest file)
  • 元数据层追踪表的架构、分区信息和所有数据文件的位置

底层 - Data Layer (数据层)

  • 包含实际存储数据的文件(data files)
  • 清单文件(manifest files)指向这些数据文件

通过快照(snapshots)实现表的time travel和历史版本访问, 通过更新catalog中的元数据指针来实现原子操作


客户表目前不包含任何数据。因此,metadata文件夹中只有一个元数据文件。一旦插入一些数据,将看到一个data文件夹,用于保存数据文件。

show_tables_files(ICEBERG_CUSTOMER_TABLE)

image-20250312215930620

Glue Data Catalog保存指向最新元数据文件*metadata.json的指针。

show_current_metadata_pointer(ICEBERG_CUSTOMER_TABLE)

image-20250312220142946

image-20250312220157472

以下是元数据文件内容。它存储schema和表属性。目前没有任何快照(snapshots字段是一个空列表):

show_current_metadata_file(ICEBERG_CUSTOMER_TABLE)

{
  "format-version" : 2,
  "table-uuid" : "bd83cf61-c9d2-4ab0-985d-0824cc5b9f29",
  "location" : "s3://otfs-workshop-data-145197526627/datasets/emr_iceberg/emr_iceberg_db.db/customer_iceberg",
  "last-sequence-number" : 0,
  "last-updated-ms" : 1741784399945,
  "last-column-id" : 5,
  "current-schema-id" : 0,
  "schemas" : [ {
    "type" : "struct",
    "schema-id" : 0,
    "fields" : [ {
      "id" : 1,
      "name" : "c_customer_sk",
      "required" : false,
      "type" : "int",
      "doc" : "unique id"
    }, {
      "id" : 2,
      "name" : "c_customer_id",
      "required" : false,
      "type" : "string"
    }, {
      "id" : 3,
      "name" : "c_first_name",
      "required" : false,
      "type" : "string"
    }, {
      "id" : 4,
      "name" : "c_last_name",
      "required" : false,
      "type" : "string"
    }, {
      "id" : 5,
      "name" : "c_email_address",
      "required" : false,
      "type" : "string"
    } ]
  } ],
  "default-spec-id" : 0,
  "partition-specs" : [ {
    "spec-id" : 0,
    "fields" : [ ]
  } ],
  "last-partition-id" : 999,
  "default-sort-order-id" : 0,
  "sort-orders" : [ {
    "order-id" : 0,
    "fields" : [ ]
  } ],
  "properties" : {
    "owner" : "hadoop",
    "comment" : "This table contains customer data",
    "write.parquet.compression-codec" : "zstd"
  },
  "current-snapshot-id" : -1,
  "refs" : { },
  "snapshots" : [ ],
  "statistics" : [ ],
  "snapshot-log" : [ ],
  "metadata-log" : [ ]
}