为 Apache Iceberg 创建 BigLake 外部表
借助 BigLake 外部表,您可以以只读格式访问具有更精细访问权限控制的 Apache Iceberg 表。与适用于 Apache Iceberg 的 BigQuery 表不同,该功能可让您以可写入的格式在 BigQuery 中创建 Apache Iceberg 表。
Iceberg 是一种支持 PB 级数据表的开源表格式。Iceberg 的开放式规范让您能够对存储在对象存储区中的数据的单个副本运行多个查询引擎。
作为 BigQuery 管理员,您可以强制执行行级和列级访问权限控制,包括对表执行数据遮盖。如需了解如何在表级层设置访问权限控制,请参阅设置访问权限控制政策。将 BigQuery Storage API 用作 Dataproc 和无服务器 Spark 中表的数据源时,也会强制执行表访问权限政策。此外,BigLake 表还可与其他 BigQuery 服务进行集成。如需查看可用集成的完整列表,请参阅 BigLake 表简介。
您可以采用以下方法创建 Iceberg BigLake 表:
使用 BigLake Metastore(建议用于 Google Cloud)。BigLake Metastore 是一个自定义 Iceberg 目录。建议您对 Google Cloud 使用 BigLake Metastore,因为它可在 Spark 和 BigQuery 工作负载之间同步您的表。为此,您可以使用适用于 Apache Spark 的 BigQuery 存储过程来初始化 BigLake Metastore 并创建 Iceberg BigLake 表。但是,若要更新架构,仍需要您在 BigQuery 中运行一个更新查询。
使用 AWS Glue Data Catalog(建议用于 AWS)。建议您对 AWS 使用 AWS Glue,因为它是一个集中式元数据仓库,您可以在其中定义存储在各种 AWS 服务中的数据的结构和位置,并提供各种功能(例如自动架构发现以及与 AWS 分析工具的集成)。
使用 Iceberg JSON 元数据文件(建议用于 Azure)。如果使用 Iceberg JSON 元数据文件,则每当有表更新时,您都必须手动更新最新的元数据文件。您可以使用适用于 Apache Spark 的 BigQuery 存储过程来创建引用 Iceberg 元数据文件的 Iceberg BigLake 表。为避免这种情况,您可以对 Google Cloud 使用 BigLake Metastore,或是对 AWS 使用 AWS Glue Data Catalog。
如需查看相关限制的完整列表,请参阅限制。
准备工作
Enable the BigQuery Connection, BigQuery Reservation, and BigLake APIs.
如果您在 BigQuery 中使用 Spark 的存储过程来创建 Iceberg BigLake 表,则必须执行以下步骤:
如需将 Iceberg BigLake 表元数据和数据文件存储在 Cloud Storage 中,您还需创建 Cloud Storage 存储桶。您需要连接到该 Cloud Storage 存储桶才能访问元数据文件。请按以下步骤操作:
如果您使用的是 BigLake Metastore,请安装适用于 Apache Spark 的相应 Iceberg 自定义目录。选择与您使用的 Iceberg 版本最匹配的 Custom Catalog 版本。
Iceberg 1.5.0
:gs://spark-lib/biglake/biglake-catalog-iceberg1.5.0-0.1.1-with-dependencies.jarIceberg 1.2.0
:gs://spark-lib/biglake/biglake-catalog-iceberg1.2.0-0.1.1-with-dependencies.jarIceberg 0.14.0
:gs://spark-lib/biglake/biglake-catalog-iceberg0.14.0-0.1.1-with-dependencies.jar
所需的角色
如需确保 BigLake API 的调用方拥有创建 BigLake 表所需的权限,请让管理员向 BigLake API 的调用方授予项目的以下 IAM 角色:
-
BigQuery Admin (
roles/bigquery.admin
) -
BigLake Admin (
roles/biglake.admin
)
如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
这些预定义角色包含创建 BigLake 表所需的权限。如需查看所需的确切权限,请展开所需权限部分:
所需权限
如需创建 BigLake 表,需要以下权限:
-
bigquery.tables.create
-
bigquery.connections.delegate
-
bigquery.jobs.create
您的管理员也可以使用自定义角色或其他预定义角色向 BigLake API 的调用方授予这些权限。
此外,如需允许 BigQuery 用户查询表,与连接关联的服务账号必须具有 BigLake Viewer (roles/biglake.viewer
) 角色,以及包含该数据的 Cloud Storage 存储桶的访问权限。
如需使用 BigLake Metastore 创建 Iceberg BigLake 表,则 BigLake API 的调用方会更改。您必须向 Dataproc 或 Spark 服务账号授予访问包含该数据的 Cloud Storage 存储桶的权限:
如果您在 Dataproc 上运行 Spark,则 Dataproc 中的调用方是 Dataproc 服务账号。
如果您在 BigQuery 中运行 Spark 过程,则调用方是 Spark 连接服务账号。
使用 BigLake Metastore 创建表
我们建议您使用 BigLake Metastore 创建 Iceberg BigLake 表。您可以使用 Apache Spark 创建这些表。一种执行此操作的便捷方法是使用 Spark 的 BigQuery 存储过程,具体步骤如下:
转到 BigQuery 页面。
在探索器窗格中,点击项目中您用于创建连接资源的连接。
如需为 Spark 创建存储过程,请点击
创建存储过程。在查询编辑器中,使用显示的
CREATE PROCEDURE
语句修改示例代码,以初始化 BigLake Metastore 并为 Iceberg 创建 BigLake 外部表:# Creates a stored procedure that initializes BLMS and database. # Creates a table in the database and populates a few rows of data. CREATE OR REPLACE PROCEDURE iceberg_demo.iceberg_setup_3_3 () WITH CONNECTION `PROCEDURE_CONNECTION_PROJECT_ID.PROCEDURE_CONNECTION_REGION.PROCEDURE_CONNECTION_ID` OPTIONS(engine="SPARK", jar_uris=["gs://spark-lib/biglake/biglake-catalog-iceberg1.2.0-0.1.0-with-dependencies.jar"], properties=[ ("spark.jars.packages","org.apache.iceberg:iceberg-spark-runtime-3.3_2.12:1.2.0"), ("spark.sql.catalog.CATALOG", "org.apache.iceberg.spark.SparkCatalog"), ("spark.sql.catalog.CATALOG.catalog-impl", "org.apache.iceberg.gcp.biglake.BigLakeCatalog"), ("spark.sql.catalog.CATALOG.hms_uri", "HMS_URI"), ("spark.sql.catalog.CATALOG.gcp_project", "PROJECT_ID"), ("spark.sql.catalog.CATALOG.gcp_location", "LOCATION"), ("spark.sql.catalog.CATALOG.blms_catalog", "CATALOG"), ("spark.sql.catalog.CATALOG.warehouse", "DATA_WAREHOUSE_URI") ] ) LANGUAGE PYTHON AS R''' from pyspark.sql import SparkSession spark = SparkSession \ .builder \ .appName("BigLake Iceberg Example") \ .enableHiveSupport() \ .getOrCreate() spark.sql("CREATE NAMESPACE IF NOT EXISTS CATALOG;") spark.sql("CREATE DATABASE IF NOT EXISTS CATALOG.CATALOG_DB;") spark.sql("DROP TABLE IF EXISTS CATALOG.CATALOG_DB.CATALOG_TABLE;") # Create a BigLake Metastore table and a BigQuery Iceberg table. spark.sql("CREATE TABLE IF NOT EXISTS CATALOG.CATALOG_DB.CATALOG_TABLE (id bigint, demo_name string) USING iceberg TBLPROPERTIES(bq_table='BQ_DATASET.BQ_TABLE', bq_connection='TABLE_CONNECTION_PROJECT_ID.TABLE_CONNECTION_REGION.TABLE_CONNECTION_ID'); ") # Copy a Hive Metastore table to BigLake Metastore. Can be used together with # TBLPROPERTIES `bq_table` to create a BigQuery Iceberg table. spark.sql("CREATE TABLE CATALOG.CATALOG_DB.CATALOG_TABLE (id bigint, demo_name string) USING iceberg TBLPROPERTIES(hms_table='HMS_DB.HMS_TABLE');") ''';
替换以下内容:
PROCEDURE_CONNECTION_PROJECT_ID
:包含用于运行 Spark 过程的连接的项目,例如myproject
。PROCEDURE_CONNECTION_REGION
:包含用于运行 Spark 过程的连接的区域,例如us
。PROCEDURE_CONNECTION_ID
:连接 ID,例如myconnection
。当您在 Google Cloud 控制台中查看连接详情时,连接 ID 是连接 ID 中显示的完全限定连接 ID 的最后一部分中的值,例如
projects/myproject/locations/connection_location/connections/myconnection
。CATALOG
:要为 BigLake Metastore 创建的 Iceberg 目录的名称。默认值为
iceberg
。HMS_URI
:如果您要将现有的 Hive Metastore 表复制到 BigLake Metastore,请指定 Hive Metastore URI。例如
thrift://localhost:9083
。PROJECT_ID
:要在其中创建 BigLake Metastore 实例的项目的 ID。Iceberg BigLake 表也会在同一项目中创建。
LOCATION
:要在其中创建 BigLake Metastore 实例的位置。BigQuery 只能访问存储在相同位置的 BigLake Metastore 实例。
DATA_WAREHOUSE_URI
:您为存储 Iceberg 元数据和数据文件而创建的 Cloud Storage 存储桶的 URI。例如
gs://mybucket/iceberg-warehouse
。CATALOG_DB
:您要在 BigLake Metastore 中创建的数据库的名称。此数据库等效于将包含 Iceberg BigLake 表的 BigQuery 数据集。
CATALOG_TABLE
:您要在 BigLake Metastore 中创建的表的名称。此表等效于要创建的 Iceberg BigLake 表。
BQ_DATASET
:包含 Iceberg BigLake 表的 BigQuery 数据集。BQ_TABLE
:您要创建的 Iceberg BigLake 表。TABLE_CONNECTION_PROJECT_ID
:包含用于创建 BigLake 表的连接的项目,例如myproject
。TABLE_CONNECTION_REGION
:包含用于创建 BigLake 表的连接的区域,例如us
。TABLE_CONNECTION_ID
:连接 ID,例如myconnection
。当您在 Google Cloud 控制台中查看连接详情时,连接 ID 是连接 ID 中显示的完全限定连接 ID 的最后一部分中的值,例如
projects/myproject/locations/connection_location/connections/myconnection
。与该连接关联的服务账号必须具有
roles/biglake.viewer
才能允许 BigQuery 用户查询表。HMS_DB
:如果您要将现有的 Hive Metastore 表复制到 BigLake Metastore,请指定 Hive Metastore 数据库。HMS_TABLE
:如果您要将现有 Hive Metastore 表复制到 BigLake Metastore,请指定 Hive Metastore 表。
如需了解 Iceberg 目录配置,请参阅 Spark 目录。
如需运行存储过程,请点击运行。如需了解详情,请参阅调用 Spark 存储过程。系统会在 BigQuery 中为 Iceberg 创建一个 BigLake 外部表。
使用元数据文件创建表
您可以使用 JSON 元数据文件为 Iceberg 创建 BigLake 外部表。但不建议使用这种方法,因为您必须手动更新 JSON 元数据文件的 URI 才能使 BigLake 表保持最新状态。如果 URI 未保持最新状态,BigQuery 中的查询可能会失败,或是导致提供的结果与直接使用 Iceberg 目录的查询引擎提供的结果不同。为了避免出现这种情况,请在创建 Iceberg BigLake 表时引用 BigLake Metastore 实例。
系统将在您创建使用 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
。
- AWS 示例:
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 元数据文件为 Iceberg 创建 BigLake 外部表,请将表定义更新为最新表元数据。如需更新架构或元数据文件,请选择以下任一方法:
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
。
设置访问权限控制政策
您可以使用多种方法来控制对 BigLake 表的访问权限:
例如,假设您要限制数据集 mydataset
中表 mytable
的行访问权限:
+---------+---------+-------+ | country | product | price | +---------+---------+-------+ | US | phone | 100 | | JP | tablet | 300 | | UK | laptop | 200 | +---------+---------+-------+
您可以为 Kim (kim@example.com
) 创建行级过滤条件,限制其仅可访问 country
为 US
的行。
CREATE ROW ACCESS POLICY only_us_filter ON mydataset.mytable GRANT TO ('user:kim@example.com') FILTER USING (country = 'US');
之后,Kim 运行以下查询:
SELECT * FROM projectid.mydataset.mytable;
输出将仅显示 country
为 US
的行:
+---------+---------+-------+ | 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 表还具有以下限制:
支持
copy-on-write
配置,但不支持merge-on-read
配置。如需了解详情,请参阅 Iceberg 配置。BigQuery 支持使用所有 Iceberg 分区转换函数进行清单删减,但
Bucket
除外。如需了解如何删减分区,请参阅查询分区表。与分区列相比,引用 Iceberg 的 BigLake 外部表的查询必须在谓词中包含字面量。仅支持 Apache Parquet 数据文件。
如果您使用的是 BigLake Metastore,则存在以下限制:
- BigQuery Omni 区域不支持 BigLake Metastore。
- 重命名表时,目标表必须与源表位于同一数据库中。必须明确指定目标表的数据库。
- 检查 Iceberg 元数据表时,您必须使用完全限定的表名称。例如
prod.db.table.history
。
费用
对于向 BigLake Metastore 发起的每 6,250,000 个请求以及存储在 BigLake Metastore 中的每 625,000 个对象,您将按需(每 TB)查询定价支付 1 TB 的费用。按需查询价格因区域而异。对于少量请求或对象,您需要支付 1 TB 的适当费用。
例如,如果您向 BigLake Metastore 发出了 6,250,000 个请求并在其中存储了 312,500 个对象,则将按照创建 BigLake Metastore 实例所在区域的按需查询价格费率支付 1.5 TB 的费用。
需要分区过滤条件
您可以通过为 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
。
- AWS 示例:
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
。
- AWS 示例:
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
标志。
例如:
如需更新默认项目中 mydataset
的 mypartitionedtable
,请输入以下命令:
bq update --require_partition_filter PROJECT_ID:DATASET.TABLE
后续步骤
- 了解 Spark 的存储过程。
- 了解 BigLake 表。
- 了解访问权限控制政策。
- 了解如何在 BigQuery 中运行查询。
- 了解 BigQuery 中支持的语句和 SQL 方言。