创建 Apache Iceberg 只读外部表
借助 Apache Iceberg 只读外部表,您可以采用只读格式访问具有更精细访问权限控制的 Apache Iceberg 表。此功能与适用于 Apache Iceberg 的 BigQuery BigLake 表不同,后者可让您采用可写格式在 BigQuery 中创建 Iceberg 表。
Iceberg 是一种支持 PB 级数据表的开源表格式。Iceberg 的开放式规范让您能够对存储在对象存储区中的数据的单个副本运行多个查询引擎。Apache Iceberg 只读外部表(以下简称 Iceberg 只读表)支持 Iceberg 规范版本 2,包括读取时合并。
作为 BigQuery 管理员,您可以强制执行行级和列级访问权限控制,包括对表执行数据遮盖。如需了解如何在表级层设置访问权限控制,请参阅设置访问权限控制政策。当您将 BigQuery Storage API 用作 Dataproc 和 Serverless Spark 中表的数据源时,系统也会强制执行表访问权限政策。
您可以通过以下方式创建 Iceberg 只读表:
使用 BigLake metastore(建议用于 Google Cloud)。BigLake metastore 基于 BigQuery 目录,并直接与 BigQuery 集成。BigLake metastore 中的表可通过多个开源引擎进行更改,并且可以通过 BigQuery 查询相同的表。BigLake metastore 还支持与 Apache Spark 直接集成。
使用 AWS Glue Data Catalog(建议用于 AWS)。建议您对 AWS 使用 AWS Glue,因为它是一个集中式元数据仓库,您可以在其中定义存储在各种 AWS 服务中的数据的结构和位置,并提供各种功能(例如自动架构发现以及与 AWS 分析工具的集成)。
使用 Iceberg JSON 元数据文件(建议用于 Azure)。如果使用 Iceberg JSON 元数据文件,则每当有表更新时,您都必须手动更新最新的元数据文件。您可以使用适用于 Apache Spark 的 BigQuery 存储过程来创建引用 Iceberg 元数据文件的 Iceberg 只读表。
如需查看相关限制的完整列表,请参阅限制。
准备工作
Enable the BigQuery Connection and BigQuery Reservation APIs.
如果您在 BigQuery 中使用 Spark 的存储过程来创建 Iceberg 只读表,则必须执行以下步骤:
如需将 Iceberg 只读表元数据和数据文件存储在 Cloud Storage 中,请创建 Cloud Storage 存储桶。您需要连接到该 Cloud Storage 存储桶才能访问元数据文件。请按以下步骤操作:
所需的角色
如需获取创建 Iceberg 只读表所需的权限,请让您的管理员授予该项目的以下 IAM 角色:
-
BigQuery Admin (
roles/bigquery.admin
) -
Storage Object Admin (
roles/storage.objectAdmin
)
如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
这些预定义角色包含创建 Iceberg 只读表所需的权限。如需查看所需的确切权限,请展开所需权限部分:
所需权限
创建 Iceberg 只读表需要以下权限:
-
bigquery.tables.create
-
bigquery.connections.delegate
-
bigquery.jobs.create
使用 BigLake metastore 创建表
我们建议您使用 BigLake metastore 创建 Iceberg 只读表。您可以使用 Apache Spark 创建这些表。一种执行此操作的便捷方法是使用 BigQuery 存储过程。如需查看示例,请参阅创建和运行存储过程。
使用元数据文件创建表
您可以使用 JSON 元数据文件创建 Iceberg 只读表。但不建议使用这种方法,因为您必须手动更新 JSON 元数据文件的 URI 才能使 Iceberg 只读表保持最新状态。如果 URI 未保持最新状态,BigQuery 中的查询可能会失败,或是导致提供的结果与直接使用 Iceberg 目录的查询引擎提供的结果不同。
系统将在您创建使用 Spark 的 Iceberg 表时指定的 Cloud Storage 存储桶中创建 Iceberg 表元数据文件。
从下列选项中选择一项:
SQL
使用 CREATE EXTERNAL TABLE
语句。 以下示例创建了一个名为 myexternal-table
的 Iceberg 只读表:
CREATE EXTERNAL TABLE myexternal-table WITH CONNECTION `myproject.us.myconnection` OPTIONS ( format = 'ICEBERG', uris = ["gs://mybucket/mydata/mytable/metadata/iceberg.metadata.json"] )
将 uris
值替换为特定表快照的最新 JSON 元数据文件。
您可以通过设置 require_partition_filter
标志来启用需要分区过滤条件。
bq
在命令行环境中,将 bq mk --table
命令与 @connection
修饰器结合使用,指定要在 --external_table_definition
参数末尾使用的连接。如需启用需要分区过滤条件,请使用 --require_partition_filter
。
bq mk
--table
--external_table_definition=TABLE_FORMAT=URI@projects/CONNECTION_PROJECT_ID/locations/CONNECTION_REGION/connections/CONNECTION_ID
PROJECT_ID:DATASET.EXTERNAL_TABLE
替换以下内容:
TABLE_FORMAT
:要创建的表的格式在此示例中为
ICEBERG
。URI
:特定表快照的最新 JSON 元数据文件。例如
gs://mybucket/mydata/mytable/metadata/iceberg.metadata.json
。URI 也可以指向外部云端位置,例如 Amazon S3 或 Azure Blob Storage。
- AWS 示例:
s3://mybucket/iceberg/metadata/1234.metadata.json
。 - Azure 示例:
azure://mystorageaccount.blob.core.windows.net/mycontainer/iceberg/metadata/1234.metadata.json
。
- AWS 示例:
CONNECTION_PROJECT_ID
:包含用于创建 Iceberg 只读表的连接的项目,例如myproject
CONNECTION_REGION
:包含用于创建 Iceberg 只读表的连接的区域,例如us
CONNECTION_ID
:表连接 ID,例如myconnection
当您在 Google Cloud 控制台中查看连接详情时,连接 ID 是连接 ID 中显示的完全限定连接 ID 的最后一部分的值,例如
projects/myproject/locations/connection_location/connections/myconnection
DATASET
:要在其中创建表的 BigQuery 数据集的名称例如
mydataset
。EXTERNAL_TABLE
:您要创建的表的名称例如
mytable
。
更新表元数据
如果您使用 JSON 元数据文件来创建 Iceberg 只读表,请将表定义更新为最新表元数据。如需更新架构或元数据文件,请选择以下任一选项:
bq
创建表定义文件:
bq mkdef --source_format=ICEBERG \ "URI" > TABLE_DEFINITION_FILE
使用带有
--autodetect_schema
标志的bq update
命令。bq update --autodetect_schema --external_table_definition=TABLE_DEFINITION_FILE PROJECT_ID:DATASET.TABLE
替换以下内容:
URI
:包含最新 JSON 元数据文件的 Cloud Storage URI例如
gs://mybucket/us/iceberg/mytable/metadata/1234.metadata.json
。TABLE_DEFINITION_FILE
:包含表架构的文件的名称PROJECT_ID
:要更新的表所属的项目的 IDDATASET
:包含要更新的表的数据集TABLE
:要更新的表
API
使用 tables.patch
方法,并将 autodetect_schema
属性设置为 true
:
PATCH https://bigquery.googleapis.com/bigquery/v2/projects/PROJECT_ID/datasets/DATASET/tables/TABLE?autodetect_schema=true
替换以下内容:
PROJECT_ID
:要更新的表所属的项目的 IDDATASET
:包含要更新的表的数据集TABLE
:要更新的表
在请求正文中,为以下字段指定更新后的值:
{ "externalDataConfiguration": { "sourceFormat": "ICEBERG", "sourceUris": [ "URI" ] }, "schema": null }'
将 URI
替换为最新的 Iceberg 元数据文件。例如 gs://mybucket/us/iceberg/mytable/metadata/1234.metadata.json
。
设置访问权限控制政策
您可以通过列级安全性、行级安全性和数据遮盖来控制对 Iceberg 只读表的访问权限。
查询 Iceberg 只读表
如需了解详情,请参阅查询 Iceberg 数据。
数据映射
BigQuery 会将 Iceberg 数据类型转换为 BigQuery 数据类型,如下表所示:
Iceberg 数据类型 | BigQuery 数据类型 |
---|---|
boolean |
BOOL |
int |
INT64 |
long |
INT64 |
float |
FLOAT64 |
double |
FLOAT64 |
Decimal(P/S) |
NUMERIC or BIG_NUMERIC depending on precision |
date |
DATE |
time |
TIME |
timestamp |
DATETIME |
timestamptz |
TIMESTAMP |
string |
STRING |
uuid |
BYTES |
fixed(L) |
BYTES |
binary |
BYTES |
list<Type> |
ARRAY<Type> |
struct |
STRUCT |
map<KeyType, ValueType> |
ARRAY<Struct<key KeyType, value ValueType>> |
限制
Iceberg 只读表具有外部表限制和以下限制:
使用“读取时合并”功能的表具有以下限制:
- 每个数据文件最多可与 10,000 个删除文件相关联。
- 一个删除文件中最多只能应用 100,000 个相等 ID。
- 您可以通过以下方式解决这些限制:频繁压缩删除文件,或者在 Iceberg 表之上创建可避免频繁变更分区的视图。
BigQuery 支持使用所有 Iceberg 分区转换函数进行清单删减,但
Bucket
除外。如需了解如何删减分区,请参阅查询分区表。引用 Iceberg 只读表的查询,其谓词中与分区列进行比较的部分必须包含字面量。仅支持 Apache Parquet 数据文件。
读取时合并费用
读取时合并数据的按需结算费用是扫描以下各项数据的费用总和:
- 在数据文件中读取的所有逻辑字节(包括通过位置删除和相等性删除标记为已删除的行)。
- 为查找数据文件中的已删除行而加载相等性删除和位置删除文件所读取的逻辑字节。
需要分区过滤条件
您可以通过为 Iceberg 表启用需要分区过滤条件选项来要求使用谓词过滤条件。如果启用此选项,则尝试在未指定与每个清单文件一致的 WHERE
子句的情况下查询表会产生以下错误:
Cannot query over table project_id.dataset.table without a filter that can be used for partition elimination.
每个清单文件都需要至少一个适合分区消除的谓词。
在创建 Iceberg 表时,您可以通过以下方式启用 require_partition_filter
:
SQL
使用 CREATE EXTERNAL TABLE
语句。以下示例会创建一个启用了需要分区过滤条件的 Iceberg 只读表,名为 TABLE
:
CREATE EXTERNAL TABLE TABLE WITH CONNECTION `PROJECT_ID.REGION.CONNECTION_ID` OPTIONS ( format = 'ICEBERG', uris = [URI], require_partition_filter = true )
替换以下内容:
TABLE
:您要创建的表的名称。PROJECT_ID
:包含您要创建的表的项目的 ID。REGION
:您要在其中创建 Iceberg 表的位置。CONNECTION_ID
:连接 ID。例如myconnection
。URI
:包含最新 JSON 元数据文件的 Cloud Storage URI。例如
gs://mybucket/us/iceberg/mytable/metadata/1234.metadata.json
。URI 也可以指向外部云端位置,例如 Amazon S3 或 Azure Blob Storage。
- AWS 示例:
s3://mybucket/iceberg/metadata/1234.metadata.json
。 - Azure 示例:
azure://mystorageaccount.blob.core.windows.net/mycontainer/iceberg/metadata/1234.metadata.json
。
- AWS 示例:
bq
将 bq mk --table
命令与 @connection
修饰器结合使用,指定要在 --external_table_definition
参数末尾使用的连接。使用 --require_partition_filter
启用需要分区过滤条件。以下示例会创建一个名为 TABLE
的 Iceberg 只读表,并启用需要分区过滤条件:
bq mk \ --table \ --external_table_definition=ICEBERG=URI@projects/CONNECTION_PROJECT_ID/locations/CONNECTION_REGION/connections/CONNECTION_ID \ PROJECT_ID:DATASET.EXTERNAL_TABLE \ --require_partition_filter
替换以下内容:
URI
:特定表快照的最新 JSON 元数据文件例如
gs://mybucket/mydata/mytable/metadata/iceberg.metadata.json
。URI 也可以指向外部云端位置,例如 Amazon S3 或 Azure Blob Storage。
- AWS 示例:
s3://mybucket/iceberg/metadata/1234.metadata.json
。 - Azure 示例:
azure://mystorageaccount.blob.core.windows.net/mycontainer/iceberg/metadata/1234.metadata.json
。
- AWS 示例:
CONNECTION_PROJECT_ID
:包含用于创建 Iceberg 只读表的连接的项目,例如myproject
CONNECTION_REGION
:包含用于创建 Iceberg 只读表的连接的区域。例如us
。CONNECTION_ID
:连接 ID。例如myconnection
。当您在 Google Cloud 控制台中查看连接详情时,连接 ID 是连接 ID 中显示的完全限定连接 ID 的最后一部分的值,例如
projects/myproject/locations/connection_location/connections/myconnection
DATASET
:包含您要更新的表的BigQuery 数据集的名称。例如
mydataset
。EXTERNAL_TABLE
:要创建的表的名称例如
mytable
。
您还可以更新 Iceberg 表以启用需要分区过滤条件。
如果您在创建分区表时未启用需要分区过滤条件选项,则可以更新表来添加该选项。
bq
使用 bq update
命令并提供 --require_partition_filter
标志。
例如:
如需更新默认项目中 mydataset
的 mypartitionedtable
,请输入以下命令:
bq update --require_partition_filter PROJECT_ID:DATASET.TABLE
后续步骤
- 了解 Spark 的存储过程。
- 了解访问权限控制政策。
- 了解如何在 BigQuery 中运行查询。
- 了解 BigQuery 中支持的语句和 SQL 方言。