返回
RSS Snowflake Engineering (Medium) AI 逐段翻译 发布 2026-09-17 00:36 收录于 09-19

Snowflake实时分析:可复现的亚秒级延迟基准测试

DataHot 速览

本文针对Snowflake Interactive Warehouse在亚秒级实时查询场景下进行可复现基准测试,并公开完整GitHub代码。作者对比了ClickHouse、Iceberg、Databricks Lakehouse RT(Reyden引擎)等方案,指出实时引擎往往需要独立安全模型与数据副本,而Snowflake试图复用既有治理模型。文中质疑Databricks公布的258毫秒查询10亿行、620毫秒742行等数据缺乏可复现性,强调实时分析性能数据应当可验证。

为什么值得关注:面向数据平台与实时分析从业者,提供可复现的基准方法而非厂商营销数字,有助评估湖仓实时查询方案的延迟与治理权衡。

本文目录 14 节
  1. 交互式查询的必要性
  2. 让我们深入了解这个可复现的基准测试
  3. Interactive Warehouse 与常规仓库对比
  4. Interactive Table 与 Snowflake Native 对比
  5. Interactive Table 与 External Iceberg 对比
  6. Interactive Table 与带 Masking Policy 的 Interactive Table 对比
  7. 更多细节
  8. 最佳实践
  9. 预热你的仓库
  10. 墙钟延迟与服务器端延迟
  11. 并发
  12. 查询模式
  13. 参数化你的查询
  14. 结论

译文

AI 逐段翻译

本文所表达的观点仅代表我个人,不一定反映我当前、过去或未来雇主的观点。

我们现在正处于一个智能体时代,各种引擎组合在一起,试图为实时需求提供查询服务。为了服务各类用户,企业最终不得不把 ETL 管道、CDC 流和/或缓存层拼接在一起。实时引擎(如 ClickHouse)需要自己的安全模型,并且需要一份你的数据副本。Iceberg 减轻了数据移动的负担,但没有解决权限问题。这非常让人想起 2015 年 Hadoop 与数据仓库争夺同一份数据副本的日子。

我在 2022 年写过如何用 Snowpipe Streaming 补齐这一差距中摄取的那一半——在事件发生后几秒内把数据导入 Snowflake。本文讲的是服务的那一半。Snowflake 的 Interactive Warehouse 旨在补齐查询侧的差距:以亚秒级延迟服务这些数据,并使用你已有的治理模型,而不是另搞一套需要管理的模型。下面的基准测试正是对此进行检验。

在 Snowflake 上进行流式处理

Databricks 也声称其搭载 Reyden 引擎的 Lakehouse RT 产品能解决这个问题。遗憾的是,他们的产品仍处于预览阶段,而且根据一段 2026 年 8 月的视频,他们的引擎在620 毫秒内推送 742 行

在另一篇帖子中,Ali Ghodsi 转发了一个说法,称 Reyden 引擎能在 258 毫秒内查询 10 亿行。我无法复现 258 毫秒或 620 毫秒这两种说法。

我看到他的帖子时恰好正在做这个基准测试。这也是为什么在分享数字时透明度很重要。这类数据点应当是可重复和/或可验证的。

让我们看看 Snowflake 的 Interactive Warehouse 使用可重复的步骤和代码表现如何。完整的GitHub 代码可在此处获取:

GitHub - sfc-gh-pneedleman/realtime_analytics_benchmark:Snowflake 上的实时分析:面向大规模亚秒级延迟的可重复基准测试

交互式查询的必要性

实时仪表盘、由数据驱动的 API 和 AI 智能体都有同样的需求:许多人(或智能体)同时提出类似的问题,并期望在亚秒级得到答案。这与夜间 ETL 作业或分析师运行临时查询是不同的 问题。关键不在于你能投入多少数据和算力,而在于你能以多快的速度同时服务多少这类查询。

过去,这需要搭建一个单独的服务层。这对业务用户和智能体来说是实实在在的运维开销。Snowflake 的 Interactive Warehouse 就是为了在不增加额外基础设施的情况下补齐这一差距,在你已有的数据上,以高并发提供亚秒级、可预测的延迟。

这并不是关于并行运行更多查询,而是关于每个查询完成的速度有多快。Interactive Warehouse 会在本地缓存中保持你的表处于预热状态,并让它们通过一个针对短小、高选择性查询调优的查询引擎运行,因此每个查询完成得更快。这使并发槽位每秒能更频繁地释放和重新填充,从而在相同连接数下表现为更高的实际 QPS。

让我们深入了解这个可复现的基准测试

如上所述,代码可在我的GitHub 仓库中获取。我的目标是模拟真实分析生产工作负载的高并发特性,使用各种表类型和模式来压测交互式仓库。以下是测试内容。

  • Snowflake 原生表
  • Snowflake 交互式表
  • 外部 Iceberg 表
  • 带脱敏策略的 Snowflake 交互式表

对于每张表,我运行了两种不同的查询:一种点查找(PL),返回单行;另一种聚合查询,模拟 Customer 360(Agg)查询。请注意,脱敏策略查询测试没有运行聚合,只运行了点查找。两种查询都在 10 到 1000 个并发连接的水平下运行。该脚本使用闭环模型,每个并行连接在上一个查询返回的瞬间发起下一个查询。

-- =====================================================================
-- Real-Time Analytics on Snowflake — Benchmark Query Reference
-- Query patterns tested against TXN_HISTORY_IT (1B rows, 100M customers)
-- =====================================================================

-- ---------------------------------------------------------------------
-- 1. POINT LOOKUP
-- Returns exactly 1 row: No GROUP BY.
-- ---------------------------------------------------------------------
SELECT
    COUNT(*),
    SUM(UNIT_PRICE * QUANTITY)
FROM SNOW_DB.SNOW_SCHEMA.TXN_HISTORY_IT
WHERE CUSTOMER_ID = %s;  -- bind parameter, not a literal value


-- ---------------------------------------------------------------------
-- 2. CUSTOMER 360 (AGGREGATION)
-- Same filter as Point Lookup, but breaks the same customer's
-- transactions with GROUP BY. Returns ~10 rows on average.
-- ---------------------------------------------------------------------
SELECT
    PRODUCT_CATEGORY,
    STORE_ID,
    COUNT(*),
    SUM(UNIT_PRICE * QUANTITY)   AS SPEND,
    MIN(TXN_DATE)                AS FIRST_PURCHASE,
    MAX(TXN_DATE)                AS LAST_PURCHASE
FROM SNOW_DB.SNOW_SCHEMA.TXN_HISTORY_IT
WHERE CUSTOMER_ID = %s
GROUP BY 1, 2
ORDER BY 4 DESC;


-- ---------------------------------------------------------------------
-- 3. POINT LOOKUP (EMAIL) — masking policy test
-- Identical shape to the Point Lookup query, but also selects
-- CUSTOMER_EMAIL (masked column). 
-- ---------------------------------------------------------------------
SELECT
    ANY_VALUE(CUSTOMER_EMAIL), --masked column 
    COUNT(*),
    SUM(UNIT_PRICE * QUANTITY)
FROM SNOW_DB.SNOW_SCHEMA.TXN_HISTORY_IT
WHERE CUSTOMER_ID = %s;


-- Note: every %s above is a bind parameter (randomized CUSTOMER_ID per call)
-- This lets Snowflake reuse cached query plan across every execution 
-- see "Parameterize your queries" in Best Practices.

注意:我测试到最多 1,000 个并发连接,因为超过这个点,瓶颈就变成了客户端,而不是 Snowflake。从单台机器生成 1,000 多个真正并发的查询,让 Python 跨多个进程不堪重负。1,000 已足以显示趋势:线性扩展,以及在 250 之后由第二个集群支持额外需求。

以下数字是使用 XS 大小的 Interactive Warehouse,在 10 到 250 的并发水平下生成的。超过 250 的并发后,高端(p90)开始出现变慢,这意味着仓库开始排队查询。Snowflake 能够垂直和水平扩展。迁移到带两个集群的 Small 仓库最能处理更高的吞吐量并实现线性扩展。

为了展示这一工作负载真正的“单一平台”特性,我对各种表组合进行了基准测试:Snowflake 原生表和外部 Iceberg 表。这两种表类型现在都已正式可用——你可以在此处阅读更多关于交互式仓库的内容:

Snowflake 交互式分析 | Snowflake 文档

这对你意味着什么:无需复制或移动数据即可获得类似结果。对于每种表类型,我都会与交互式表基线进行比较。

Interactive Warehouse 与常规仓库对比

在确立了 Interactive Warehouse 的必要性之后,第一项比较将其付诸检验以建立基线。相同的表和查询,在 Interactive Warehouse 与常规(非交互式)仓库上运行,并发连接数从 10 到 1,000。

注意QPS 定义为每 60 秒窗口内的查询数,在服务端通过 ACCOUNT_USAGE 测量(COUNT(status='SUCCESS')/60)——不是客户端观测到的,也不计入超时或错误。

注 2:在此基准测试的全部 236 万次查询中——涵盖所有表类型、查询模式和并发级别——错误率均为 0%。没有失败,也没有查询触及 Interactive Warehouse 的 5 秒超时。

当并发达到 250 时,与标准 warehouse 一样,你可以添加更多计算集群并继续看到线性扩展。在这个点查询示例中,运行峰值超过 2,300 QPS 使用的是带两个集群的 Small Warehouse。两个查询都在 500 连接时扩展到 Multi-Cluster 以继续线性扩展。在这两种情况下,Snowflake 都能够处理并发需求。

每秒查询数与延迟之间也存在高度相关性。查询持续时间越短,Snowflake 每分钟能处理的查询就越多。Interactive 查询的突出之处在于,查询的 p90(低于 90%)在 < 100ms 内返回。即使常规 warehouse 很快(亚秒级),当查询量增加时也无法跟上。使用 interactive 时,p90 保持相对平稳。

Interactive Table 与 Snowflake Native 对比

Interactive Warehouse 的对比表明 warehouse 很重要。下一个问题是表格式是否也重要——标准 Snowflake 表在无需迁移或物化的情况下,是否能在同一 Interactive Warehouse 上表现得与专门构建的 Interactive Table 一样好?

在 1,000 并发连接时,Snowflake Native 提供了 2,277 QPS,而 Interactive Table 为 2,349 QPS,吞吐量略有 3% 的差异。标准表,无需数据移动,与专门构建的 Interactive Table 不相上下。此功能在撰写博客时刚刚 GA,结果说明了问题。

对于 p90 客户 360 聚合查询来说,延迟是有趣的趋势。即使该查询在 250 并发时 p90 徘徊在 300ms 左右,两种表类型在此查询上的 QPS 仍保持在彼此 19% 以内,这是测试中差距最大的一次。这再次表明 warehouse 在此节点附近开始排队,因为聚合查询更大。未显示的是 Native Snowflake 表上此查询发生了约 200ms 的排队。其他查询在 250 级别也有轻微排队,导致 p90 延迟增加。这正是我在 c=500 时进行纵向和横向扩展的原因。让你的集群与需求相匹配是关键。

Interactive Table 与 External Iceberg 对比

之前的测试都使用 Snowflake 管理的表。下一个问题是 Snowflake 能否直接在其不拥有或不管理的数据上服务相同的交互式工作负载——一个外部写入、通过 catalog 链接的 Iceberg 表,而不将其复制到 Snowflake。

在此测试中,我使用了 catalog 链接的 Iceberg 表来模拟外部引擎(例如 Spark)将数据写入外部 catalog(例如 Glue Catalog),而 Snowflake 作为读取方。这是一个更困难的测试,因为 Iceberg 表通过外部 catalog 从远程对象存储读取。我演示这一点是为了展示 Snowflake 如何在不复制数据的情况下用作单一服务引擎。

在 1,000 并发连接时,Iceberg 表保持 2,102 QPS,而 Interactive Table 为 2,349——低约 11%。这种方法有轻微的权衡,但如果你的 SLA 能支持略低的吞吐量,它可以减少你移动数据的需求。

Iceberg 也显示出类似的趋势,p90 客户 360 聚合查询的延迟出现尖峰。点查询在所有并发测试中都保持自身水平,响应时间约为 200ms。额外的数据行和聚合使客户 360 查询尖峰到超过 700ms——这告诉我,对于 Iceberg 在此并发级别,更大的集群可能会有帮助。

Interactive Table 与带 Masking Policy 的 Interactive Table 对比

剩下的问题是治理是否会妨碍其中任何一项。对列应用 masking policy 是否会为本已亚秒级的查询增加有意义的延迟?

我想强调在 interactive table 上使用现有治理策略——这可能不是一个常见用例,说实话,我也不知道会发生什么。运行点查询时,我投影了另一个列 email,策略使用正则表达式将其显示为 ***@email。

CASE WHEN CURRENT_ROLE() IN (‘SECURITYADMIN’, ‘ACCOUNTADMIN’) THEN val
ELSE REGEXP_REPLACE(val, '^[^@]+', '***') END

在整个并发测试中,masked 查询的吞吐量只有很小的差异。

对我来说,令人惊讶的部分是执行时间仍然低于 250 毫秒,即使在每分钟内需要对超过 143,000 条数据进行掩码处理的情况下也是如此。图表中没有显示,但我分解了编译和执行时间,以更好地理解为什么 p90 时间较高。掩码查询额外有 40–110 毫秒的编译时间——这才是延迟更高的原因,而不是额外的列本身。

更多细节

对于构建者来说,如果你还没有查看 GitHub,Snowflake 设置脚本是一个很好的起点。它包含了用于复现数据集的查询以及用于开始试用的交互式仓库。

realtime_analytics_benchmark/sf_setup.sql at main · sfc-gh-pneedleman/realtime_analytics_benchmark

对于数据方面的人员,这些数字背后的详细信息列在这个公开的 Google Sheet 中。

如果你对数据或测试方法有任何问题,请联系我们。

最佳实践

预热你的仓库

你的生产环境、你的用户需求可能是突发的,但你会知道高峰(市场开盘、班次开始、营销推广)和低谷(周末、晚间)。使用 Snowflake Tasks 在已知高峰到来之前将你的交互式仓库集群数量扩展上去,然后在高峰过后再缩减回来。

我在本次基准测试中没有从冷启动进行测试。首先运行了一次预热以将仓库加载到缓存中,然后我测量了结果。这模拟的是实时生产工作负载,而不是冷启动。此外,Snowflake 支持将表添加到你的仓库中,这样当仓库启动时缓存会预先预热。这适用于标准表、Iceberg 表、动态表或交互式表——在需求到来之前至少提前 10 分钟将它们添加进去。

墙钟延迟与服务器端延迟

本基准测试中的数字使用的是服务器端延迟,取自 ACCOUNT_USAGE。这是 Snowflake 所测量的,而不是你的客户端或代理实际会记录到的。墙钟延迟同样重要,甚至比服务器端更重要。Snowflake 上 50 毫秒 + 500 毫秒的网络延迟 = 半秒。

本基准测试没有将其纳入考虑,因为你的客户端所在位置(本地部署 vs 云)、你的驱动程序、连接池和代理设置存在差异。在代码库中,它包含了墙钟指标,因此你可以在服务器端指标之外查看它们。在我的设置(本地部署的 MacBook Pro)中,我看到了额外的约 150–175 毫秒的客户端/网络开销——你可以使用该工具来查看数字如何分解以及延迟在哪里堆积。

并发

我运行了一个闭环客户端——16 个 Python 进程,每个都有自己的连接池,在上一个查询返回后立即发起下一个查询。

在仓库端,我将 MAX_CONCURRENCY_LEVEL (MCL) 设置为 32,高于默认值 8。单独来看,MCL=32 并没有怎么提升 QPS。它带来的是余量——当大量查询同时涌入时,更高的 MCL 会立即启动更多查询,而不是将它们排队。一旦你运行多集群,这个余量就更加重要。根据你的流量实际情况设置 MCL,无论你是否使用 MCW。你会想要针对你的工作负载测试所有这些数字(进程数、MCL、MCW)。

你可以将并发推到超过 c=1000——只需确保你的客户端确实能够产生这样的需求。在高并发下,负载生成器可能在仓库之前就成为瓶颈,所以在信任这些数字之前,请根据你的核心数来扩展你的进程/线程数。

查询模式

在开始测试交互式仓库之前,先测试你的查询。按 CUSTOMER_ID 进行聚簇是让常规仓库点查找变快的原因,同样的聚簇也延续到了交互式仓库。为你的访问模式设置正确的聚簇键(或搜索优化)比其背后的仓库规模更重要。在测试之前检查分区剪枝,并利用 Snowflake 查询的一般最佳实践。如果 Snowflake 没有进行剪枝,仓库规模也解决不了问题。

一个反直觉的提示:更少的分区并不自动更好——它们通常会在分区的 min/max 范围之间产生更多重叠,从而损害剪枝效果。更多的微分区或文件可以减少这种重叠,让 Snowflake 在每次查询时跳过更多分区。如果使用 Iceberg 进行测试,考虑将文件大小目标设为 16MB(而不是默认的 128MB),以便优化器可以剪枝更多文件。

参数化你的查询

本基准测试中的每次点查找和聚合都使用了绑定参数(例如 WHERE CUSTOMER_ID=?),而不是 SQL 文本中的字面值。这让 Snowflake 可以在每次调用中复用缓存的查询计划,而不是为每个唯一值重新编译——这也是你在本基准测试中看到的低编译时间背后的同一机制。如果你正在构建数据驱动的 API 或代理工作负载,请参数化你的查询;硬编码字面值会降低计划缓存的效果,并会表现为额外的延迟。

结论

可重复的基准测试结果很明确。Snowflake 的交互式仓库提供了生产级的亚秒级延迟和线性并发扩展能力,而无需 专门的引擎、CDC 管道或单独的安全模型来管理。还记得那个“十亿行上 258 毫秒”的说法吗?那是在一个仍处于预览阶段的产品上的一次查询。交互式表在一个十亿行的表上实现了低于 125 毫秒的延迟,并在一个已经正式发布(GA)的功能上,在 1,000 个并发连接下持续保持了这一水平。

但吞吐量甚至都不是最大的惊喜——一个标准的 Snowflake 表,甚至是一个零拷贝直接查询的外部 Iceberg 表,在使用你现有数据的情况下,与专门构建的交互式表相比表现都很好。

本博客在撰写时考虑了可重复性。你的数据和查询模式是不同的,所以真正的测试是你自己运行它。我请那些对实时分析感兴趣的人试一试,无论你的表是标准表、Iceberg 表还是交互式表。而且,与所有 Snowflake 功能一样,它们会随着时间的推移不断改进。请关注这个领域,因为它只会从这里继续成熟。

我很想听听你的发现,并继续在评论中讨论。

Snowflake 上的实时分析:面向大规模亚秒级延迟的可重复基准测试最初发布于Snowflake Builders 博客:数据工程师、应用开发者、AI 与数据科学在 Medium 上,人们通过高亮并回应这个故事来继续对话。

这篇内容对你有用吗?

反馈只用于改善内容筛选,不等同于收藏

分享这条资讯
分享海报
保存图片
iOS 也可以长按图片保存