适用于 Apache Iceberg 的 BigQuery 表
若要在预览版期间获得支持,请发送电子邮件至 bigquery-tables-for-apache-iceberg-help@google.com。
适用于 Apache Iceberg 的 BigQuery 表(以下称为“Iceberg 表”)为在 Google Cloud上构建开放格式湖仓一体提供了基础。Iceberg 表提供与 BigQuery 表相同的全托管式体验,但使用 Parquet 将数据存储在客户拥有的存储桶中,以便与 Iceberg 开放表格式进行互操作。
适用于 Apache Iceberg 的 BigQuery 表不同于适用于 Apache Iceberg 的 BigLake 外部表,因为只有适用于 Apache Iceberg 的 BigQuery 表可直接在 BigQuery 中修改。适用于 Apache Iceberg 的 BigLake 外部表是从其他查询引擎(例如 Apache Spark)生成的只读表,只能使用 BigQuery 进行查询。
Iceberg 表支持以下功能:
- 使用 GoogleSQL 数据操纵语言 (DML) 进行表变更。
- 通过适用于 Spark、Dataflow 和其他引擎的 BigLake 连接器使用 Storage Write API 进行统一批处理和高吞吐量流式处理。
- 架构演变:您可以添加、删除和重命名列,以满足您的需求。借助此功能,您还可以更改现有列的数据类型和列模式。如需了解详情,请参阅类型转换规则。
- 自动存储优化,包括自适应文件大小调整、自动聚簇、垃圾回收和元数据优化。
- 列级安全性和数据遮盖。
架构
Iceberg 表可为位于您自己的云存储分区中的表提供 BigQuery 资源管理的便利。Iceberg 可让您在这些表上使用 BigQuery,而无需将数据从您控制的存储分区中移出。
下图简要展示了托管式表架构:
此表管理会对存储桶产生以下影响:
- BigQuery 会在存储桶中创建新的数据文件,以响应写入请求和后台存储优化(例如 DML 语句和流式处理)。
- 当您在 BigQuery 中删除托管式表时,BigQuery 不会删除关联的数据文件。您必须通过手动从存储桶中删除文件和所有导出的表元数据来确认删除。
- Iceberg 表不会产生 BigQuery 存储费用。如需了解详情,请参阅结算。
创建 Iceberg 表与创建 BigQuery 表类似。由于 Iceberg 表以开放格式在 Cloud Storage 上存储数据,因此在以下方面提供更多选项:
- 使用
WITH CONNECTION
指定 Cloud 资源连接,以便为 BigLake 访问 Cloud Storage 配置连接凭据。 - 使用
file_format
指定数据存储的文件格式。预览版支持PARQUET
。 - 使用
table_format
指定开源元数据表格式。预览版支持ICEBERG
。
最佳做法
直接在 BigQuery 外部更改或向存储桶添加文件可能会导致数据丢失或不可恢复的错误。下表介绍了可能的场景:
操作 | 结果 | 预防措施 |
---|---|---|
向 BigQuery 外部的存储桶添加新文件。 | 数据丢失:BigQuery 不会跟踪在 BigQuery 外部添加的新文件或对象。未跟踪的文件会被后台垃圾回收进程删除。 | 仅通过 BigQuery 添加数据。这可让 BigQuery 跟踪这些文件并防止它们被垃圾回收。 为防止意外添加和数据丢失,我们还建议您限制对包含 Iceberg 表的存储桶的外部工具写入权限。 |
在非空前缀中创建新的 Iceberg 表。 | 数据丢失:BigQuery 不会跟踪现有数据,因此这些文件会被视为未跟踪,并由后台垃圾回收进程删除。 | 仅在空前缀中创建新的 Iceberg 表。 |
修改或替换 Iceberg 表数据文件。 | 数据丢失:在外部修改或替换时,表会无法通过一致性检查,并且变得不可读。对表进行的查询会失败。 您无法通过自助方式从这个时间点恢复。请与支持团队联系,寻求数据恢复方面的帮助。 |
仅通过 BigQuery 修改数据。这可让 BigQuery 跟踪这些文件并防止它们被垃圾回收。 为防止意外添加和数据丢失,我们还建议您限制对包含 Iceberg 表的存储桶的外部工具写入权限。 |
在同一 URI 或重叠的 URI 上为 Apache Iceberg 创建两个 BigQuery 表。 | 数据丢失:BigQuery 不会桥接 Iceberg 表的相同 URI 实例。每个表的后台垃圾回收进程都会将相反表的文件视为未跟踪,并将其删除,从而导致数据丢失。 | 为每个 Iceberg 表使用不同的 URI。 |
位置注意事项
您可以借助 Cloud Storage 单区域或双区域存储分区(而不是多区域存储分区)来提高性能。
结算
以下功能使用现有已发布的价格计费:
- Cloud Storage 价格,适用于存储在 Cloud Storage 存储桶中的所有数据、Cloud Storage 执行的数据处理,以及从存储桶读取的数据量的网络用量。
- BigQuery 计算价格,适用于查询、DML 和后台存储优化(包括聚簇、合并和垃圾回收)。
- 使用预订(槽)的费用遵循现有的槽价格。
- 使用按需库存单位 (SKU) 的费用遵循现有的按需价格。如需了解详情,请参阅 BigLake 费用。
- 批量加载和提取计算使用按需 SKU 或预留(槽)计费。
- Storage Read API 价格,适用于通过 Read API 从 Spark 读取数据。
- Storage Write API 价格,适用于流式处理。
Iceberg 表工作流
以下部分介绍了如何创建、加载、管理和查询托管式表。
准备工作
在创建和使用 Iceberg 表之前,请确保您已设置与存储桶的 Cloud 资源连接。您的连接需要具有对存储桶的写入权限,如以下所需角色部分中所述。
所需的角色
如需获得让 BigQuery 管理项目中的表所需的权限,请让您的管理员为您授予以下 IAM 角色:
-
创建 Iceberg 表:
-
针对项目的 BigQuery Data Owner (
roles/bigquery.dataOwner
) -
针对项目的 BigQuery Connection Admin (
roles/bigquery.connectionAdmin
)
-
针对项目的 BigQuery Data Owner (
-
查询 Iceberg 表:
-
针对项目的 BigQuery Data Viewer (
roles/bigquery.dataViewer
) -
针对项目的 BigQuery User (
roles/bigquery.user
)
-
针对项目的 BigQuery Data Viewer (
-
为了让连接服务账号在 Cloud Storage 中读取和写入数据:
-
针对存储桶的 Storage Object Admin (
roles/storage.objectAdmin
) -
针对存储桶的 Storage Legacy Bucket Reader (
roles/storage.legacyBucketReader
)
-
针对存储桶的 Storage Object Admin (
如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
这些预定义角色可提供让 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_list
的format
行。
bq
bq load \ --source_format=FILE_FORMAT \ MANAGED_TABLE \ STORAGE_URI
替换以下内容:
- FILE_FORMAT:源表格式。如需了解支持的格式,请参阅
load_option_list
的format
行。 - 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 表元数据快照,请按以下步骤操作:
使用
EXPORT TABLE METADATA
SQL 语句将元数据导出为 Iceberg 格式。可选:安排 Iceberg 元数据快照刷新。如需根据设定的间隔时间刷新 Iceberg 元数据快照,请使用定期查询。
以下示例使用 DDL 语句 EXPORT TABLE METADATA FROM mydataset.test
创建名为 My Scheduled Snapshot Refresh Query
的定期查询。目标数据集为 mydataset
。DDL 语句每 24 小时运行一次。
bq query \
--use_legacy_sql=false \
--destination_dataset=mydataset
--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;
请注意,mydataset
和 table_name
是实际数据集和表的占位符。
使用 Apache Spark 读取 Iceberg 表
使用 HadoopCatalog
在 Apache Spark 中设置和读取表数据。
以下示例会将您的环境设置为搭配使用 Spark SQL 与 Apache 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 表将所有数据存储在 Cloud Storage 中。您需要为所有存储的数据付费,包括历史表数据。您可能还需要支付 Cloud Storage 数据处理和传输费用(如适用)。无需支付 BigQuery 特定的存储费用。如需了解详情,请参阅 Cloud Storage 价格。
存储优化
Iceberg 表需要存储优化操作,例如文件合并和重新聚簇。这些优化操作使用企业版随用随付型槽,而不是使用现有的 BACKGROUND
预留。
通过 BigQuery Storage Write API 进行流式传输时发生的数据导出操作包含在 Storage Write API 价格中,不会作为后台维护计费。如需了解详情,请参阅数据注入价格。
存储空间优化用量显示在 INFORMATION_SCHEMA.JOBS
视图中。
查询和作业
与 BigQuery 表类似,如果您使用 BigQuery 按需价格,则需要为查询和读取的字节(每 TiB)付费;如果您使用 BigQuery 容量计算价格,则需要为槽使用量(每个槽每小时)付费。
BigQuery 的价格也适用于 BigQuery Storage Read API 和 BigQuery Storage 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 表不支持以下表架构:
EXPORT METADATA
不支持包含精度大于 38 位数的BIGNUMERIC
或NUMERIC
数据类型的表。- Iceberg 表不支持以下架构演变场景:
NUMERIC
到FLOAT
类型强制转换INT
到FLOAT
类型强制转换- 使用 SQL DDL 语句向现有
RECORD
列添加新的嵌套字段
- 通过控制台或 API 查询时,Iceberg 会显示 0 字节的存储大小。
- Iceberg 表不支持物化视图。
- Iceberg 表不支持多语句事务。
- Iceberg 表不支持 Change Data Capture (CDC) 更新。
- 使用 BigQuery Storage Write API 将数据流式传输到 Iceberg 表时,您必须先停用查询缓存。
- Iceberg 表不支持托管式灾难恢复
- Iceberg 表不支持分区。请考虑使用聚簇作为替代方案。
- Iceberg 表不支持行级安全性。
- Iceberg 表不支持时间旅行。
- Iceberg 表不支持故障安全时间范围。
- Iceberg 表不支持提取作业。
INFORMATION_SCHEMA.TABLE_STORAGE
视图不包含 Iceberg 表。- 不支持将 Iceberg 表用作查询结果目标。
CREATE OR REPLACE
不支持将标准表替换为 Iceberg 表,也不支持将 Iceberg 表替换为标准表。- 批量加载和
LOAD DATA
语句仅支持将数据附加到现有 Iceberg 表。 - 批量加载和
LOAD DATA
语句不支持架构更新。 TRUNCATE TABLE
不支持 Iceberg 表。可以使用两种替代方案:CREATE OR REPLACE TABLE
,使用相同的表创建选项。DELETE FROM
表WHERE
true
APPENDS
表值函数 (TVF) 不支持 Iceberg 表。- Apache Spark 中的 Iceberg 导出内容不包含写入优化存储中最近流式传输的数据。
- 快速加载不支持具有灵活列名称的文件。
- 使用
tabledata.list
基于记录的分页访问不支持 Iceberg 表。- Iceberg 表不支持关联数据集。