为 Apache Iceberg 创建 BigLake 外部表

借助 BigLake 外部表,您可以采用只读格式访问具有更精细访问权限控制的 Apache Iceberg 表。此功能与适用于 Apache Iceberg 的 BigQuery 表不同,后者可让您采用可写格式在 BigQuery 中创建 Apache Iceberg 表。

Iceberg 是一种支持 PB 级数据表的开源表格式。Iceberg 的开放式规范让您能够对存储在对象存储区中的数据的单个副本运行多个查询引擎。适用于 Apache Iceberg 的 BigLake 外部表(以下简称 BigLake Iceberg 表)支持 Iceberg 规范版本 2,包括“读取时合并”功能。

作为 BigQuery 管理员,您可以强制执行行级和列级访问权限控制,包括对表执行数据遮盖。如需了解如何在表级层设置访问权限控制,请参阅设置访问权限控制政策。将 BigQuery Storage API 用作 Dataproc 和无服务器 Spark 中表的数据源时,也会强制执行表访问权限政策。此外,BigLake 表还可与其他 BigQuery 服务进行集成。如需查看可用集成的完整列表,请参阅 BigLake 表简介

您可以采用以下方法创建 Iceberg BigLake 表:

  • 使用 BigQuery Metastore(建议用于 Google Cloud)BigQuery Metastore 基于 BigQuery 目录,并直接与 BigQuery 集成。BigQuery Metastore 中的表可通过多个开源引擎进行更改,并且可以通过 BigQuery 查询相同的表。BigQuery Metastore 还支持与 Apache Spark 直接集成。

  • 使用 AWS Glue Data Catalog(建议用于 AWS)。建议您对 AWS 使用 AWS Glue,因为它是一个集中式元数据仓库,您可以在其中定义存储在各种 AWS 服务中的数据的结构和位置,并提供各种功能(例如自动架构发现以及与 AWS 分析工具的集成)。

  • 使用 Iceberg JSON 元数据文件(建议用于 Azure)。如果使用 Iceberg JSON 元数据文件,则每当有表更新时,您都必须手动更新最新的元数据文件。您可以使用适用于 Apache Spark 的 BigQuery 存储过程来创建引用 Iceberg 元数据文件的 Iceberg BigLake 表。

    如需查看相关限制的完整列表,请参阅限制

准备工作

所需的角色

如需获得创建 BigLake 表所需的权限,请让管理员向您授予项目的以下 IAM 角色:

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

这些预定义角色包含创建 BigLake 表所需的权限。如需查看所需的确切权限,请展开所需权限部分:

所需权限

如需创建 BigLake 表,需要以下权限:

  • bigquery.tables.create
  • bigquery.connections.delegate
  • bigquery.jobs.create

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

使用 BigQuery metastore 创建表

我们建议您使用 BigQuery Metastore 创建 Iceberg BigLake 表。您可以使用 Apache Spark 创建这些表。一种执行此操作的便捷方法是使用 BigQuery 存储过程。如需查看示例,请参阅创建和运行存储过程

使用元数据文件创建表

您可以使用 JSON 元数据文件创建 BigLake Iceberg 表。但不建议使用这种方法,因为您必须手动更新 JSON 元数据文件的 URI 才能使 BigLake 表保持最新状态。如果 URI 未保持最新状态,BigQuery 中的查询可能会失败,或是导致提供的结果与直接使用 Iceberg 目录的其他查询引擎提供的结果不同。

系统将在您创建使用 Spark 的 Iceberg 表时指定的 Cloud Storage 存储桶中创建 Iceberg 表元数据文件。

从下列选项中选择一项:

SQL

使用 CREATE EXTERNAL TABLE 语句。 以下示例将创建一个名为 myexternal-table 的 BigLake 表:

  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
  • CONNECTION_PROJECT_ID:包含用于创建 BigLake 表的连接的项目,例如 myproject

  • CONNECTION_REGION:包含用于创建 BigLake 表的连接的区域,例如 us

  • CONNECTION_ID:表连接 ID,例如 myconnection

    当您在 Google Cloud 控制台中查看连接详情时,连接 ID 是连接 ID 中显示的完全限定连接 ID 的最后一部分中的值,例如 projects/myproject/locations/connection_location/connections/myconnection

  • DATASET:要在其中创建表的 BigQuery 数据集的名称

    例如 mydataset

  • EXTERNAL_TABLE:您要创建的表的名称

    例如 mytable

更新表元数据

如果您使用 JSON 元数据文件创建 BigLake Iceberg 表,请将表定义更新为最新表元数据。如需更新架构或元数据文件,请选择以下任一方法:

bq

  1. 创建表定义文件:

    bq mkdef --source_format=ICEBERG \
    "URI" > TABLE_DEFINITION_FILE
    
  2. 使用带有 --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:要更新的表所属的项目的 ID

    • DATASET:包含要更新的表的数据集

    • 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:要更新的表所属的项目的 ID
  • DATASET:包含要更新的表的数据集
  • TABLE:要更新的表

在请求正文中,为以下字段指定更新后的值:

{
     "externalDataConfiguration": {
      "sourceFormat": "ICEBERG",
      "sourceUris": [
        "URI"
      ]
    },
    "schema": null
  }'

URI 替换为最新的 Iceberg 元数据文件。例如 gs://mybucket/us/iceberg/mytable/metadata/1234.metadata.json

设置访问权限控制政策

您可以使用多种方法来控制对 BigLake 表的访问权限:

例如,假设您要限制数据集 mydataset 中表 mytable 的行访问权限:

+---------+---------+-------+
| country | product | price |
+---------+---------+-------+
| US      | phone   |   100 |
| JP      | tablet  |   300 |
| UK      | laptop  |   200 |
+---------+---------+-------+

您可以为 Kim ([email protected]) 创建行级过滤条件,限制其仅可访问 countryUS 的行。

CREATE ROW ACCESS POLICY only_us_filter
ON mydataset.mytable
GRANT TO ('user:[email protected]')
FILTER USING (country = 'US');

之后,Kim 运行以下查询:

SELECT * FROM projectid.mydataset.mytable;

输出将仅显示 countryUS 的行:

+---------+---------+-------+
| country | product | price |
+---------+---------+-------+
| US      | phone   |   100 |
+---------+---------+-------+

查询 BigLake 表

如需了解详情,请参阅查询 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>>

限制

除了 BigLake 表限制之外,Iceberg BigLake 表还具有以下限制:

  • 使用“按读取合并”的表存在以下限制:

    • 每个数据文件最多可以与 10,000 个删除文件相关联。
    • 一个删除文件中最多只能应用 10 万个等式 ID。
    • 您可以通过以下方法来规避这些限制:经常压缩删除文件,或者在 Iceberg 表上创建一个视图,以避免频繁更改分区。
  • BigQuery 支持使用所有 Iceberg 分区转换函数进行清单删减,但 Bucket 除外。如需了解如何删减分区,请参阅查询分区表。与分区列相比,引用 BigLake 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 语句。以下示例会创建一个启用了需要分区过滤条件的 BigLake 表,名为 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

bq

bq mk --table 命令@connection 修饰器结合使用,指定要在 --external_table_definition 参数末尾使用的连接。使用 --require_partition_filter 启用需要分区过滤条件。以下示例会创建一个启用了需要分区过滤条件的 BigLake 表,名为 TABLE

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
  • CONNECTION_PROJECT_ID:包含用于创建 BigLake 表的连接的项目,例如 myproject

  • CONNECTION_REGION:包含用于创建 BigLake 表的连接的区域。例如 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 标志。

例如:

如需更新默认项目中 mydatasetmypartitionedtable,请输入以下命令:

bq update --require_partition_filter PROJECT_ID:DATASET.TABLE

后续步骤