跨云分析最昂贵的环节,往往不是 SQL 计算,而是把数据从一个云搬到另一个云。BigQuery 新近预览的跨云缓存没有要求企业复制整座数据湖,而是把查询实际读取的 Parquet 数据块缓存在 Google Cloud 本地区域,让后续查询尽量复用已有数据。
这项能力面向两类场景:通过 Lakehouse 目录联邦访问 Iceberg 表,以及通过 BigQuery 跨云连接直接查询 Amazon S3、Azure Storage 中的 CSV、JSON 和临时 Parquet 文件。它仍处于预览阶段,但已经展示出一种更务实的多云路径:计算靠近缓存,数据仍留在原系统中。
跨云查询的成本,为什么不能只看逻辑扫描量
假设一张 Iceberg 销售表有 10 TiB。分析师查询其中几个字段时,BigQuery 可能在逻辑上处理数百 GiB,但这不意味着同样多的数据必须穿过云边界。
这里有三层缩减机制:
- 分区裁剪:跳过与过滤条件无关的文件或分区。
- 列式压缩与投影:Parquet 只读取查询涉及的列块,Zstandard 等压缩算法进一步减少物理字节数。
- 跨云缓存:已经读取过的列块保存在 BigQuery 所在的 Google Cloud 区域,后续查询只拉取新增部分。
来源示例中,第一次查询逻辑处理约 214.5 GiB,但从 Amazon S3 实际读取约 24.1 GiB。分析师随后增加配送方式维度时,BigQuery 从本地缓存复用了 24.1 GiB,只额外从 S3 拉取约 1.33 GiB,缓存命中率达到 94.8%。
关键点在于,缓存不是以整张表甚至整个文件为单位。对于 Parquet,BigQuery 可以缓存查询投影到的列块和字典页。用户增加一个维度时,不必重新传输此前已经读取的所有列。
缓存命中并不等于读取旧数据
跨云缓存最容易引起的疑问是:源端对象更新后,查询会不会继续读到旧块?
BigQuery 在使用缓存前会检查远端对象元数据,确认对象没有变化,并验证用户仍然拥有访问权限。如果上游表发生修改,查询会获取新的文件;不再被引用的缓存块则会自动过期。这使缓存仍以远端数据为单一事实来源,而不是形成一套需要单独同步的数据副本。
安全和隔离机制也需要纳入架构评审:
- 缓存块默认使用 Google 管理的加密密钥静态加密。
- 缓存按照项目和目录边界隔离,降低跨租户暴露风险。
- 查询执行与本地缓存固定在配置的 Google Cloud 区域,例如
us-east4。 - 即使数据主体命中缓存,系统仍可能访问远端元数据,因此网络、权限和源端服务必须保持可用。
区域固定有助于满足数据驻留要求,但不能代替合规审查。团队仍需确认源数据所在区域、互联链路、缓存区域以及访问日志是否满足自身监管要求。
Iceberg 目录联邦还是跨云连接
两种接入方式解决的问题不同,不应仅因为都支持缓存就混为一谈。
| 数据形态 | 建议入口 | 适用原因 |
|---|---|---|
| 由 Unity Catalog、AWS Glue 或 Snowflake Horizon 管理的 Iceberg 表 | Lakehouse 目录联邦 | 自动同步表结构和快照,查询最新 Iceberg 元数据 |
| S3 或 Azure Storage 中的独立 CSV、JSON、Parquet 文件 | BigQuery 跨云连接 | 可以直接把远端 bucket 路径映射为外部表 |
| 需要表级治理、模式演进和快照语义的数据产品 | 优先 Iceberg 目录联邦 | 避免把文件路径当成长期的数据管理接口 |
| 临时数据交换或尚未纳入目录的原始文件 | 优先跨云连接 | 接入成本较低,适合过渡和探索 |
跨云连接采用 Google Cloud 区域内的标准 BigQuery 计算工作器,而不是在其他云中部署专用计算工作器。这有利于扩展区域覆盖,并让远端文件使用更多 BigQuery 能力,包括 BigQuery AI 和 Gemini 相关功能。具体功能范围仍应以预览版本和目标区域实际支持情况为准。
用两次相邻查询观察缓存复用
下面的 SQL 使用摘要中的 TPC-DS 风格表名。运行前需要把目录、数据集和字段名改成自己的环境,并确保对应 Iceberg 目录已经联邦到 BigQuery。第一条查询只按站点统计晚间 8 点的销售数据:
SELECT
ws.ws_web_site_sk AS web_site_key,
COUNT(*) AS total_transactions,
ROUND(SUM(ws.ws_sales_price), 2) AS total_sales
FROM `aws_lakehouse_catalog.sales.web_sales` AS ws
JOIN `aws_lakehouse_catalog.sales.time_dim` AS t
ON ws.ws_sold_time_sk = t.t_time_sk
WHERE t.t_hour = 20
GROUP BY web_site_key
ORDER BY total_sales DESC;
第二条查询保留原有列,再加入配送方式。它适合验证子文件级缓存是否能复用第一次查询读取过的列块:
SELECT
ws.ws_web_site_sk AS web_site_key,
sm.sm_type AS shipping_method,
COUNT(*) AS total_transactions,
ROUND(SUM(ws.ws_sales_price), 2) AS total_sales
FROM `aws_lakehouse_catalog.sales.web_sales` AS ws
JOIN `aws_lakehouse_catalog.sales.time_dim` AS t
ON ws.ws_sold_time_sk = t.t_time_sk
JOIN `aws_lakehouse_catalog.sales.ship_mode` AS sm
ON ws.ws_ship_mode_sk = sm.sm_ship_mode_sk
WHERE t.t_hour = 20
GROUP BY web_site_key, shipping_method
ORDER BY total_sales DESC;
可以在 Cloud Shell 或安装了 Google Cloud CLI 的终端中执行。先修改项目、区域和 SQL 文件名:
export PROJECT_ID="my-gcp-project"
export LOCATION="us-east4"
gcloud config set project "$PROJECT_ID"
bq query \
--use_legacy_sql=false \
--location="$LOCATION" \
< first-query.sql
bq query \
--use_legacy_sql=false \
--location="$LOCATION" \
< second-query.sql
在 BigQuery 作业详情中比较两次查询的 objectStorageBytesRead 与 cacheBytesRead。第一次冷查询通常会看到缓存读取为零;第二次查询如果复用了相同列块,缓存读取量会上升,而远端对象存储读取量应主要来自新增列或新增表。实际结果取决于过滤条件、文件布局、对象是否更新、缓存是否过期以及区域配置,因此不要把示例命中率当作服务保证。
用一个简单模型估算网络成本
跨云传输量可以用下面的近似公式评估:
跨云传输量 ≈ 逻辑处理量 ÷ 压缩比 ×(1 - 缓存命中率)
如果逻辑处理量为 1 TiB、压缩比为 8:1、缓存命中率为 80%,估算结果是:
1 TiB ÷ 8 × 20% ≈ 25.6 GiB
也就是不到逻辑处理量的 3%。来源同时指出,结合 Iceberg 列式压缩和跨云缓存,某些工作负载跨云传输的数据可以低于处理量的 5%。这不是所有查询都能达到的固定比例:全列扫描、低压缩率数据、频繁改写的对象和低重复度查询都会降低收益。
上线前值得检查的事项
跨云缓存最适合具有重复访问模式的分析、仪表盘和 AI 工作流。若准备试点,可以从以下清单开始:
- 选择读取频繁、更新节奏相对稳定的 Iceberg 表,而不是先迁移所有数据集。
- 把首次冷查询和后续热查询分开统计,记录逻辑处理量、远端读取量、缓存读取量与总延迟。
- 检查 Parquet 文件大小、分区策略、排序方式和压缩算法;缓存无法弥补糟糕的数据布局。
- 确认 BigQuery 区域、远端存储区域和私有互联路径,评估实际每 GiB 传输成本。
- 验证源端对象更新、权限撤销和目录快照变化后,查询结果仍符合新鲜度要求。
- 在生产承诺中明确标注该能力仍处于预览阶段,并准备功能变化或区域限制的应对方案。
这套架构并没有让跨云传输消失,而是把传输单位从“整份数据”缩小到“当前查询尚未缓存的列块”。对于不断围绕同一批事实表增加维度、过滤条件和 AI 推理步骤的工作负载,这种细粒度复用往往比复制整座数据湖更容易控制成本。