Apache Iceberg 受管理表

Apache Iceberg 受管表(以前称为“BigQuery 中的 Apache Iceberg BigLake 表”)为在 Google Cloud上构建开放格式湖仓一体提供了基础。Iceberg 受管表提供与标准 BigQuery 表相同的全代管式体验,但将数据存储在客户拥有的存储分区中。Iceberg 受管表支持开放式 Iceberg 表格式,可在单个数据副本上与开源和第三方计算引擎实现更好的互操作性。

Iceberg 受管表支持以下功能:

  • 使用 GoogleSQL 数据操纵语言 (DML) 进行表变更。
  • 通过 Spark、Dataflow 和其他引擎等连接器使用 BigQuery Storage Write API 进行统一批处理和高吞吐量流式处理。
  • 在每次表格变更时执行 Iceberg V2 快照导出和自动刷新,以便使用开源和第三方查询引擎(例如 Spark)直接查询。
  • 架构演变:您可以添加、删除和重命名列,以满足您的需求。借助此功能,您还可以更改现有列的数据类型模式。 如需了解详情,请参阅转换规则
  • 自动存储优化,包括自适应文件大小调整、自动聚簇、垃圾回收和元数据优化。
  • 在 BigQuery 中使用时间旅行访问历史数据。
  • 列级安全性数据遮盖
  • 多语句事务(预览版)。
  • 表分区(预览版)。
  • Dataform 工作流中的表创建

架构

Iceberg 托管式表可为位于您自己的云存储分区中的表提供 BigQuery 资源管理的便利。您可以在这些表上使用 BigQuery 和开源计算引擎,而无需将数据从您控制的存储桶中移出。您必须先配置 Cloud Storage 存储桶,然后才能开始使用 Iceberg 受管表。

使用 Iceberg 管理式表会对存储桶产生以下影响:

  • BigQuery 会在存储桶中创建新的数据文件,以响应写入请求和后台存储优化(例如 DML 语句和流式处理)。
  • 系统会对相应存储桶中的数据文件执行自动压缩和聚簇。时间旅行窗口过期后,系统会收集数据文件。不过,如果表被删除,关联的数据文件不会被垃圾回收。如需了解详情,请参阅存储空间优化

创建 Iceberg 受管表的过程与创建 BigQuery 表类似。由于 Iceberg 表以开放格式在 Cloud Storage 上存储数据,因此您必须执行以下操作:

  • 使用 WITH CONNECTION 指定 Cloud 资源连接,以便为 BigQuery 访问 Cloud Storage 配置连接凭据。
  • 使用 file_format = PARQUET 语句将数据存储的文件格式指定为 PARQUET
  • 使用 table_format = ICEBERG 语句将开源元数据表格式指定为 ICEBERG

最佳做法

在 BigQuery 外部直接更改文件或向存储桶添加文件可能会导致数据丢失或不可恢复的错误。下表介绍了可能的场景:

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

Cloud Storage 存储桶配置最佳实践

Cloud Storage 存储桶的配置及其与 BigQuery 的连接会直接影响 Iceberg 受管表的性能、费用、数据完整性、安全性和治理。以下最佳实践可帮助您完成此配置:

  • 选择一个名称,明确表明该存储桶仅用于 Iceberg 受管表。

  • 选择与您的 BigQuery 数据集位于同一区域的单区域 Cloud Storage 存储分区。这种协调可以避免数据传输费用,从而提高性能并降低成本。

  • 默认情况下,Cloud Storage 会将数据存储在标准存储类别中,以提供足够的性能。如需优化数据存储费用,您可以启用 Autoclass 来自动管理存储类别转换。Autoclass 从标准存储类别开始,并将未被访问的对象移至越来越冷的类别,以降低存储费用。再次读取对象时,系统会将其移回 Standard 类别。

  • 启用统一存储桶级访问权限禁止公开访问

  • 验证是否已向正确的用户和服务账号分配了所需的角色

  • 为防止 Cloud Storage 存储桶中的数据意外删除或损坏,请限制贵组织中大多数用户的写入和删除权限。为此,您可以设置存储桶权限政策,并设置条件,以便拒绝所有用户(除了您指定的用户)的 PUTDELETE 请求。

  • 应用 Google 管理的客户管理的加密密钥,以便对敏感数据提供额外保护。

  • 启用审核日志记录,以实现运营透明度、问题排查和数据访问监控。

  • 保留默认的软删除政策(保留 7 天)以防止意外删除。不过,如果您发现数据已被删除,请与支持团队联系,而不是手动恢复对象,因为 BigQuery 元数据不会跟踪在 BigQuery 外部添加或修改的对象。

  • 系统会自动启用自适应文件大小调整、自动聚类和垃圾回收功能,以帮助优化文件性能和成本。

  • 请避免使用以下 Cloud Storage 功能,因为 Iceberg 受管表不支持这些功能:

您可以通过使用以下命令创建存储桶来实现这些最佳实践:

gcloud storage buckets create gs://BUCKET_NAME \
    --project=PROJECT_ID \
    --location=LOCATION \
    --enable-autoclass \
    --public-access-prevention \
    --uniform-bucket-level-access

替换以下内容:

  • BUCKET_NAME:新存储桶的名称
  • PROJECT_ID:您的项目的 ID
  • LOCATION:新存储桶的位置

Iceberg 受管表工作流

以下部分介绍了如何创建、加载、管理和查询 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_ID.]DATASET_ID.TABLE_NAME (
COLUMN DATA_TYPE[, ...]
)
CLUSTER BY CLUSTER_COLUMN_LIST
WITH CONNECTION {CONNECTION_NAME | DEFAULT}
OPTIONS (
file_format = 'PARQUET',
table_format = 'ICEBERG',
storage_uri = 'STORAGE_URI');

替换以下内容:

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

bq

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

替换以下内容:

  • PROJECT_ID:包含数据集的项目。如果未定义,该命令会假定为默认项目。
  • CONNECTION_NAME:连接的名称。 例如 myproject.us.myconnection
  • STORAGE_URI:完全限定的 Cloud Storage URI。例如 gs://mybucket/table
  • COLUMN_NAME:列名称。
  • DATA_TYPE:列中包含的信息的数据类型。
  • CLUSTER_COLUMN_LIST(可选):以英文逗号分隔的列表,最多包含四个列。它们必须是顶级非重复列。
  • DATASET_ID:现有数据集的 ID。
  • 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 受管表中。

从平面文件标准加载数据

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

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

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

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

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

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

从 Pub/Sub 加载流式数据

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

从 Iceberg 受管表中导出数据

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

将数据导出为平面格式

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

创建 Iceberg 受管表元数据快照

如需创建 Iceberg 受管表元数据快照,请按照下列步骤操作:

  1. 使用 EXPORT TABLE METADATA SQL 语句将元数据导出为 Iceberg V2 格式。

  2. 可选:安排 Iceberg 元数据快照刷新。如需根据设定的时间间隔刷新 Iceberg 元数据快照,请使用预定查询

  3. 可选:为您的项目启用元数据自动刷新功能,以便在每次表格变更时自动更新 Iceberg 表元数据快照。如需启用元数据自动刷新功能,请联系 bigquery-tables-for-apache-iceberg-help@google.com。每次刷新操作都会产生 EXPORT METADATA 费用

以下示例会使用 DDL 语句 EXPORT TABLE METADATA FROM mydataset.test 创建名为 My Scheduled Snapshot Refresh Query 的预定查询。DDL 语句每 24 小时运行一次。

bq query \
    --use_legacy_sql=false \
    --display_name='My Scheduled Snapshot Refresh Query' \
    --schedule='every 24 hours' \
    'EXPORT TABLE METADATA FROM mydataset.test'

查看 Iceberg 受管表元数据快照

在刷新 Iceberg 受管表元数据快照后,您可以在 Iceberg 受管表最初创建的 Cloud Storage URI 中找到该快照。/data 文件夹包含 Parquet 文件数据分片,/metadata 文件夹包含 Iceberg 受管表元数据快照。

SELECT
  table_name,
  REGEXP_EXTRACT(ddl, r"storage_uri\s*=\s*\"([^\"]+)\"") AS storage_uri
FROM
  `mydataset`.INFORMATION_SCHEMA.TABLES;

请注意,mydatasettable_name 是实际数据集和表的占位项。

使用 Spark 读取 Iceberg 受管表

以下示例会将您的环境设置为搭配使用 Spark SQL 与 Spark,然后执行查询以从指定的 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' \

# Query the table
SELECT * FROM CATALOG_NAME.FOLDER_NAME;

替换以下内容:

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

修改 Iceberg 代管式表

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

使用多语句事务

如需访问 Iceberg 受管表的多语句事务,请填写注册表单

使用分区

如需访问 Iceberg 代管式表的分区,请填写注册表单

通过指定用于将表分段的分区列来对表进行分区。Iceberg 受管表支持以下列类型:

  • DATE
  • DATETIME
  • TIMESTAMP

按照 DATEDATETIMETIMESTAMP 列对表进行分区称为时间单位列分区。您可以选择分区是具有每小时、每天、每月还是每年的时间粒度

Iceberg 受管表还支持聚簇结合使用聚簇表和分区表

分区限制

创建分区 Iceberg 托管式表

如需创建分区 Iceberg 受管表,请按照说明创建标准 Iceberg 受管表,并根据您的环境添加以下内容之一:

修改和查询分区 Iceberg 受管表

对于分区 Iceberg 受管表,BigQuery 数据操纵语言 (DML) 语句和查询与标准 Iceberg 受管表相同。BigQuery 会自动将作业范围限定为正确的分区,类似于 Iceberg 隐藏分区。此外,您添加到表中的任何新数据都会自动进行分区。

您还可以使用其他引擎查询分区 Iceberg 受管表,方式与查询标准 Iceberg 受管表相同。我们建议启用元数据快照,以获得最佳体验。

为了提高安全性,Iceberg 受管表的分区信息与数据路径分离,完全由元数据层管理。

价格

Iceberg 受管表价格由存储空间、存储空间优化以及查询和作业组成。

存储

Iceberg 受管理表将所有数据存储在 Cloud Storage 中。您需要为所有存储的数据付费,包括历史表数据。您还可能需要支付 Cloud Storage 数据处理转移费用。对于通过 BigQuery 或 BigQuery Storage API 处理的操作,可能会免除部分 Cloud Storage 操作费用。无需支付 BigQuery 特定的存储费用。如需了解详情,请参阅 Cloud Storage 价格

存储优化

Iceberg 受管表会执行自动表管理,包括压缩、聚簇、垃圾回收和 BigQuery 元数据生成/刷新,以优化查询性能并降低存储费用。表管理的计算资源使用量按数据计算单元 (DCU) 随时间变化以秒为增量计费。如需了解详情,请参阅 Iceberg 受管表价格

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

如需查看这些后台操作的日志和计算使用情况,请查询 INFORMATION_SCHEMA.JOBS 视图。如需查看示例查询,请参阅以下内容:

查询和作业

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

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

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

限制

Iceberg 托管式表具有以下限制:

  • Iceberg 受管表不支持重命名操作ALTER TABLE RENAME TO 语句
  • Iceberg 受管表不支持表副本CREATE TABLE COPY 语句
  • Iceberg 受管表不支持表克隆CREATE TABLE CLONE 语句
  • Iceberg 受管表不支持表快照CREATE SNAPSHOT TABLE 语句
  • Iceberg 受管表不支持以下表架构:
  • Iceberg 托管表不支持以下架构演变场景:
    • NUMERICFLOAT 类型强制转换
    • INTFLOAT 类型强制转换
    • 使用 SQL DDL 语句向现有 RECORD 列添加新的嵌套字段
  • 通过控制台或 API 查询时,Iceberg 受管表会显示 0 字节的存储大小。
  • Iceberg 代管式表不支持物化视图
  • Iceberg 受管表不支持授权视图,但支持列级访问权限控制
  • Iceberg 受管表不支持变更数据捕获 (CDC) 更新。
  • Iceberg 受管表不支持托管式灾难恢复
  • Iceberg 托管表不支持行级安全性
  • Iceberg 受管表不支持故障安全窗口
  • Iceberg 受管表不支持提取作业。
  • INFORMATION_SCHEMA.TABLE_STORAGE 视图不包含 Iceberg 托管式表。
  • 不支持将 Iceberg 代管表用作查询结果目标位置。您可以改为使用 CREATE TABLE 语句和 AS query_statement 参数来创建表作为查询结果目标。
  • CREATE OR REPLACE 不支持将标准表替换为 Iceberg 受管表,也不支持将 Iceberg 受管表替换为标准表。
  • 批量加载LOAD DATA 语句仅支持将数据附加到现有的 Iceberg 受管表。
  • 批量加载LOAD DATA 语句不支持架构更新。
  • TRUNCATE TABLE 不支持 Iceberg 受管表。有两种替代方案:
  • APPENDS 表值函数 (TVF) 不支持 Iceberg 受管表。
  • Iceberg 元数据可能不包含在过去 90 分钟内通过 Storage Write API 流式传输到 BigQuery 的数据。
  • 使用 tabledata.list 的基于记录的分页访问不支持 Iceberg 受管表。
  • 每个 Iceberg 受管表仅会运行一个并发变更 DML 语句(UPDATEDELETEMERGE)。其他变更 DML 语句将排入队列。