适用于 Apache Iceberg 的 BigQuery 表

若要在预览版期间获得支持,请发送电子邮件至 bigquery-tables-for-apache-iceberg-help@google.com

适用于 Apache Iceberg 的 BigQuery 表(以下称为“Iceberg 表”)为在 Google Cloud 上构建开放格式湖仓一体提供了基础。Iceberg 表提供与 BigQuery 表相同的全托管式体验,但使用 Parquet 将数据存储在客户拥有的存储桶中,以便与 Iceberg 开放表格式进行互操作。

Iceberg 表支持以下功能:

  • 使用 GoogleSQL 数据操纵语言 (DML) 进行表变更。
  • 通过适用于 Spark、Dataflow 和许多其他引擎的 BigLake 连接器使用 Storage Write API 进行统一批处理和高吞吐量流式处理。
  • 架构演变:您可以添加、删除和重命名列,以满足您的需求。借助此功能,您还可以更改现有列的数据类型列模式。如需了解详情,请参阅类型转换规则
  • 自动存储优化,包括自适应文件大小调整、自动聚簇、垃圾回收和元数据优化。
  • *行级安全性列级安全性数据遮盖

架构

Iceberg 表可为位于您自己的云存储桶中的表提供 BigQuery 资源管理的便利。Iceberg 可让您在这些表上使用 BigQuery,而无需将数据从您控制的存储桶中移出。

下图简要展示了托管式表架构: BigQuery for Iceberg 表架构图。

此表管理会对存储桶产生以下影响:

  • BigQuery 会在存储桶中创建新的数据文件,以响应写入请求和后台存储优化(例如 DML 语句和流式处理)。
  • 当您在 BigQuery 中删除托管式表时,BigQuery 不会删除关联的数据文件。您必须通过手动从存储桶中删除文件和所有导出的表元数据来确认删除。
  • Iceberg 表不会产生 BigQuery 存储费用。如需了解详情,请参阅结算

创建 Iceberg 表与创建 BigQuery 表类似。由于 Iceberg 表以开放格式在 Cloud Storage 上存储数据,因此在以下方面提供更多选项:

  • 使用 WITH CONNECTION 指定 Cloud 资源连接,以便为 BigLake 访问 Cloud Storage 配置连接凭据。
  • 使用 file_format 指定数据存储的文件格式。预览版支持 PARQUET
  • 使用 table_format 指定开源元数据表格式。预览版支持 ICEBERG

最佳做法

仅通过 BigQuery 修改 Iceberg 表非常重要。对存储桶进行任何直接更改或添加都可能会导致数据丢失或不可恢复的错误。下表详细介绍了可能的场景:

操作 结果 预防措施
向 BigQuery 外部的存储桶添加新文件。 数据丢失:BigQuery 不会跟踪在 BigQuery 外部添加的新文件或对象。未跟踪的文件会由后台垃圾回收进程删除。 仅通过 BigQuery 添加数据。这可让 BigQuery 跟踪这些文件并防止它们被垃圾回收。
为防止意外添加和数据丢失,我们还建议您限制对包含 Iceberg 表的存储桶的外部工具写入权限。
在非空前缀中创建新的 Iceberg 表。 数据丢失:BigQuery 不会跟踪现有数据,因此这些文件会被视为未跟踪,并由后台垃圾回收进程删除。 仅在空前缀中创建新的 Iceberg 表。
修改或替换 Iceberg 表数据文件。 数据丢失:在外部修改或替换时,表会无法通过一致性检查,并且变得不可读。对表进行的查询会失败。
您无法通过自助方式从这个时间点恢复。如需数据恢复方面的帮助,请与支持团队联系。
仅通过 BigQuery 修改数据。这可让 BigQuery 跟踪这些文件并防止它们被垃圾回收。
为防止意外添加和数据丢失,我们还建议您限制对包含 Iceberg 表的存储桶的外部工具写入权限。
在相同或重叠的 URI 上为 Apache Iceberg 创建两个 BigQuery 表。 数据丢失:BigQuery 不会桥接 Iceberg 表的相同 URI 实例。每个表的后台垃圾回收进程都会将相反表的文件视为未跟踪,并将其删除,从而导致数据丢失。 为每个 Iceberg 表使用唯一的 URI。

结算

以下功能使用现有已发布的价格计费:

  • Cloud Storage 价格,适用于存储在 Cloud Storage 存储桶中的所有数据、Cloud Storage 执行的数据处理,以及从存储桶读取的数据量的网络用量。
  • BigQuery 计算价格,适用于查询、DML 和后台存储优化(包括聚簇、合并和垃圾回收)。
    • 使用预留(槽)的费用遵循现有的槽价格。
    • 使用按需库存单位 (SKU) 的费用遵循现有的按需价格。如需了解详情,请参阅 BigLake 费用
  • 批量加载提取计算使用按需 SKU 或预留(槽)计费。
  • Storage Write API 价格,适用于通过 Read API 从 Spark 读取数据。
  • Storage Write API 价格,适用于流式处理。

Iceberg 表工作流

以下部分介绍了如何创建、加载、管理和查询托管式表。

准备工作

在创建和使用 Iceberg 表之前,请确保您已设置与存储桶的 Cloud 资源连接。您的连接需要具有对存储桶的写入权限,如以下所需角色部分中所述。

所需的角色

如需获得让 BigQuery 管理项目中的表所需的权限,请让您的管理员为您授予以下 IAM 角色:

如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

这些预定义角色可提供让 BigQuery 管理项目中的表所需的权限。如需查看所需的确切权限,请展开所需权限部分:

所需权限

让 BigQuery 管理项目中的表需要以下权限:

  • 针对您的项目的 bigquery.connections.delegate 权限
  • 针对您的项目的 bigquery.jobs.create 权限
  • 针对您的项目的 bigquery.readsessions.create 权限
  • 针对您的项目的 bigquery.tables.create 权限
  • 针对您的项目的 bigquery.tables.get 权限
  • 针对您的项目的 bigquery.tables.getData 权限
  • 针对您的项目的 storage.buckets.get 权限
  • 针对您的项目的 storage.objects.create 权限
  • 针对您的项目的 storage.objects.delete 权限
  • 针对您的项目的 storage.objects.get 权限
  • 针对您的项目的 storage.objects.list 权限

您也可以使用自定义角色或其他预定义角色来获取这些权限。

创建 Iceberg 表

如需创建 Iceberg 表,请选择以下方法之一:

SQL

CREATE TABLE [PROJECT_NAME.]DATASET_NAME.TABLE_NAME (
COLUMN DATA_TYPE[, ...]
)
CLUSTER BY CLUSTER_COLUMN_LIST
WITH CONNECTION CONNECTION_NAME
OPTIONS (
file_format = 'PARQUET',
table_format = 'ICEBERG',
storage_uri = 'STORAGE_URI');

替换以下内容:

  • PROJECT_NAME:包含数据集的项目。如果未定义,该命令会假定为默认项目。
  • DATASET_NAME:现有数据集。
  • TABLE_NAME:您要创建的表的名称。
  • DATA_TYPE:列中包含的信息的数据类型。
  • CLUSTER_COLUMN_LIST:英文逗号分隔的列表,最多包含 4 个列。它们必须是顶级非重复列。
  • CONNECTION_NAME:连接的名称。 例如 myproject.us.myconnection
  • STORAGE_URI:完全限定的 Cloud Storage URI。例如 gs://mybucket/table

bq

bq --project_id=PROJECT_NAME mk \
    --file_format=PARQUET \
    --table_format=ICEBERG \
    --connection_id=CONNECTION_NAME \
    --storage_uri=STORAGE_URI \
    --schema=COLUMN_NAME:DATA_TYPE[, ...] \
    --clustering_fields=CLUSTER_COLUMN_LIST \
    MANAGED_TABLE_NAME

替换以下内容:

  • PROJECT_NAME:包含数据集的项目。如果未定义,该命令会假定为默认项目。
  • CONNECTION_NAME:连接的名称。 例如 myproject.us.myconnection
  • STORAGE_URI:完全限定的 Cloud Storage URI。例如 gs://mybucket/table
  • COLUMN_NAME:列名称。
  • DATA_TYPE:列中包含的信息的数据类型。
  • CLUSTER_COLUMN_LIST:英文逗号分隔的列表,最多包含 4 个列。它们必须是顶级非重复列。
  • MANAGED_TABLE_NAME:您要创建的表的名称。

API

使用定义的表资源调用 tables.insert 方法,如下所示:

{
"tableReference": {
  "tableId": "TABLE_NAME"
},
"biglakeConfiguration": {
  "connectionId": "CONNECTION_NAME",
  "fileFormat": "PARQUET",
  "tableFormat": "ICEBERG",
  "storageUri": "STORAGE_URI"
},
"schema": {
  "fields": [
    {
      "name": "COLUMN_NAME",
      "type": "DATA_TYPE"
    }
    [, ...]
  ]
}
}

替换以下内容:

  • TABLE_NAME:您要创建的表的名称。
  • CONNECTION_NAME:连接的名称。 例如 myproject.us.myconnection
  • STORAGE_URI:完全限定的 Cloud Storage URI通配符也受支持。 例如 gs://mybucket/table
  • COLUMN_NAME:列名称。
  • DATA_TYPE:列中包含的信息的数据类型。

将数据导入 Iceberg 表

以下部分介绍了如何将数据从各种表格式导入 Iceberg 表中。

从 Parquet 文件快速加载

借助 copy_files_only 选项,您可以通过复制现有的 Parquet 文件(而不是读取内容并将内容重写为新文件)来更快地加载数据。与常规文件加载相比,快速加载使用更少的计算容量。Parquet 文件必须与 Apache Iceberg 规范兼容,并且包含完整的列统计信息。快速加载不会检测文件中的无效值(例如超出范围的时间戳),因为系统不会读取和重新处理文件。如需详细了解如何加载 Parquet 文件,请参阅将 Parquet 数据加载到新表中

如需将平面 Parquet 文件快速加载到现有 Iceberg 表中,请使用 bq load 命令

bq load \
    --copy_files_only \
    --source_format=PARQUET \
    DATASET_NAME.TABLE_NAME \
    PATH_TO_SOURCE

替换以下内容:

  • DATASET_NAME:包含 Iceberg 表的数据集。
  • TABLE_NAME:您要将数据加载到的 Iceberg 表的名称。
  • PATH_TO_SOURCE:完全限定的 Cloud Storage URI 或以英文逗号分隔的 URI 列表。通配符也受支持。 例如 gs://mybucket/mydata*.parquet

从平面文件标准加载数据

Iceberg 表使用 BigQuery 加载作业将外部文件加载到 Iceberg 表中。如果您已有 Iceberg 表,请按照 bq load CLI 指南LOAD SQL 指南加载外部数据。加载数据后,新的 Parquet 文件会写入 STORAGE_URI/data 文件夹。

如果使用上述说明时还没有 Iceberg 表,则改为创建 BigQuery 表。

如需查看将数据批量加载到托管式表的工具特定示例,请参阅以下内容:

SQL

LOAD DATA INTO MANAGED_TABLE_NAME
FROM FILES (
uris=['STORAGE_URI'],
format='FILE_FORMAT');

替换以下内容:

  • MANAGED_TABLE_NAME:现有 Iceberg 表的名称。
  • STORAGE_URI:完全限定的 Cloud Storage URI 或以英文逗号分隔的 URI 列表。通配符也受支持。 例如 gs://mybucket/table
  • FILE_FORMAT:源表格式。如需了解支持的格式,请参阅 load_option_listformat 行。

bq

bq load \
  --source_format=FILE_FORMAT \
  MANAGED_TABLE \
  STORAGE_URI

替换以下内容:

  • FILE_FORMAT:源表格式。如需了解支持的格式,请参阅 load_option_listformat 行。
  • MANAGED_TABLE_NAME:现有 Iceberg 表的名称。
  • STORAGE_URI:完全限定的 Cloud Storage URI 或以英文逗号分隔的 URI 列表。通配符也受支持。 例如 gs://mybucket/table

从 Hive 分区文件标准加载数据

您可以使用标准 BigQuery 加载作业将 Hive 分区文件加载到 Iceberg 表中。如需了解详情,请参阅加载外部分区数据

从 Pub/Sub 加载流式数据

您可以使用 Pub/Sub BigQuery 订阅将流式数据加载到 Iceberg 表中。

从 Iceberg 表中导出数据

以下部分介绍了如何将 Iceberg 表中的数据导出为各种表格式。

将数据导出为平面格式

如需将 Iceberg 表导出为平面格式,请使用 EXPORT DATA 语句并选择目标格式。如需了解详情,请参阅导出数据

将元数据导出为 Iceberg 表

如需将 Iceberg 表的元数据导出为 Iceberg 表,请选择以下方法之一:

bq

使用 EXPORT TABLE METADATA 语句。

以下示例会将表元数据以 Iceberg 格式导出到该表的 storage_uri 下的 metadata 文件夹中:

bq query \
  --nouse_legacy_sql \
  --nouse_cache "EXPORT TABLE METADATA FROM TABLE_NAME"

Spark

在 Apache Spark 中,您可以使用 HadoopCatalog 导出表元数据。

以下示例会将您的环境设置为搭配使用 Spark SQL 与 Apache Iceberg,建立一个目录来管理 Iceberg 表,然后执行查询以从指定的 Iceberg 表中提取数据。

spark-sql \
  --packages org.apache.iceberg:iceberg-spark-runtime-ICEBERG_VERSION_NUMBER \
  --conf spark.sql.catalog.CATALOG_NAME=org.apache.iceberg.spark.SparkCatalog \
  --conf spark.sql.catalog.CATALOG_NAME.type=hadoop \
  --conf spark.sql.catalog.CATALOG_NAME.warehouse='BUCKET_PATH' \

# Queries the table
spark-sql> SELECT * FROM CATALOG_NAME.FOLDER_NAME;

替换以下内容:

  • ICEBERG_VERSION_NUMBER:Apache Spark Iceberg 运行时的当前版本。从 Spark 版本下载最新版本。
  • CATALOG_NAME:用于引用 Iceberg 表的目录。
  • BUCKET_PATH:包含表文件的存储桶的路径。例如 gs://mybucket/
  • FOLDER_NAME:包含表文件的文件夹。例如 myfolder

修改 Iceberg 表

如需修改 Iceberg 表,请按照修改表架构中所示的步骤操作。

价格

Iceberg 表价格由三个单独的部分组成:

存储

Iceberg 表将所有数据存储在 storage_name 中。您需要为所有存储的数据付费,包括历史表数据。您还可能需要支付 Cloud Storage 数据处理传输费用(如适用)。无需支付 BigQuery 特定的存储费用。如需了解详情,请参阅 Cloud Storage 价格

存储优化

Iceberg 表需要存储优化操作,例如文件合并和重新聚簇。这些优化操作使用企业版随用随付型槽,而不是使用现有的 BACKGROUND 预留。

通过 BigQuery Storage Write API 进行流式传输时发生的数据导出操作包含在 Storage Write API 价格中,不会作为后台维护计费。如需了解详情,请参阅数据注入价格

查询和作业

与 BigQuery 表类似,如果您使用 BigQuery 按需价格,则需要为查询和读取的字节(每 TiB)付费;如果您使用 BigQuery 容量计算价格,则需要为槽使用量(每个槽每小时)付费。

BigQuery 价格也适用于 BigQuery Storage Read APIBigQuery Storage Write API

加载和导出操作(例如 EXPORT METADATA)使用企业版随用随付型槽。这与 BigQuery 表不同,后者不会针对这些操作计费。如果提供了具有企业版或企业 Plus 版槽的 PIPELINE 预留,则加载和导出操作会改为使用这些预留槽。

限制

Iceberg 表具有以下限制:

  • Iceberg 表不支持重命名操作。
  • Iceberg 表不支持以下表架构:
  • EXPORT METADATA 不支持包含以下内容的表:
    • GEOGRAPHY 数据类型
    • 精度大于 38 位的 BIGNUMERICNUMERIC 数据类型。
  • Iceberg 表不支持以下架构演变场景:
    • NUMERICFLOAT 类型强制转换
    • INTFLOAT 类型强制转换
    • 使用 SQL DDL 语句向现有 RECORD 列添加新的嵌套字段
  • 通过控制台或 API 查询时,Iceberg 会显示 0 字节的存储大小。
  • Iceberg 表不支持物化视图
  • Iceberg 表不支持多语句事务
  • Iceberg 表不支持表副本克隆快照
  • Iceberg 表不支持变更数据捕获 (CDC) 更新。
  • Iceberg 表不支持托管式灾难恢复
  • Iceberg 表不支持分区。请考虑使用聚簇作为替代方案。
  • Iceberg 表不支持行级安全性
  • Iceberg 表不支持时间旅行
  • Iceberg 表不支持故障安全窗口
  • Iceberg 表不支持提取作业。
  • INFORMATION_SCHEMA.TABLE_STORAGE 视图不包含 Iceberg 表。
  • 不支持将 Iceberg 表用作查询结果目标。
  • CREATE OR REPLACE 不支持将标准表替换为 Iceberg 表,也不支持将 Iceberg 表替换为标准表。
  • CREATE TABLE COPY 语句不支持 Iceberg 表。
  • ALTER TABLE RENAME TO 语句不支持 Iceberg 表。
  • LOAD DATA OVERWRITE 不支持将 Iceberg 表用作覆盖目标。
  • TRUNCATE TABLE 不支持 Iceberg 表。可以使用两种替代方案:
  • APPENDS 表值函数 (TVF) 不支持 Iceberg 表。
  • 将数据批量加载到 Iceberg 表中不支持:
    • 向现有表添加列。
    • 放宽列模式或类型。
    • 创建新的 Iceberg 表。
    • 覆盖表(也称为 writeDisposition WRITE_TRUNCATE)。
  • Apache Spark 中的 Iceberg 导出内容不包含写入优化存储中最近流式传输的数据。
  • 快速加载不支持具有灵活列名称的文件。