3. 成本可观测性基础

在 Snowflake 中做 FinOps,第一步不是省钱,而是“看得见”。Snowflake 把成本与用量数据分散在两个不同的系统视图体系里:ACCOUNT_USAGE 和 INFORMATION_SCHEMA。它们不是二选一的关系,而是互补关系——一个负责“历史与全局”,一个负责“实时与局部”。理解它们的差异、延迟特性和字段关联方式,是搭建任何成本看板、分摊模型或异常告警的前提。

两个视图体系的本质差异

ACCOUNT_USAGE 位于 SNOWFLAKE 数据库下,是账户级的共享视图,覆盖整个账户所有数据库、所有仓库、所有用户的历史记录。它的数据来自 Snowflake 内部元数据仓库,保留周期长(多数视图 365 天),但存在明显的数据延迟:计量类视图通常延迟约 45 分钟到 3 小时,部分视图最长可达 2 小时以上。这意味着它适合做趋势分析、月度账单核对、成本分摊,但不适合做秒级实时监控。

INFORMATION_SCHEMA 位于每个数据库内部,是数据库级的视图集合,只反映当前数据库范围内的对象与活动。它的最大优势是低延迟——查询历史、仓库使用等数据几乎实时可见(通常延迟在秒级到分钟级),但保留周期短(一般 7 天到 14 天,取决于视图),且不包含账户级的计量与费用数据。它适合做实时排障、当前会话分析、短期用量追踪。

记忆口诀:ACCOUNT_USAGE 管“钱和历史”,INFORMATION_SCHEMA 管“现在和局部”。做成本治理,两者都要用,但用途不同。

关键成本元数据表及其字段

成本可观测性最核心的三张表是:WAREHOUSE_METERING_HISTORY、QUERY_HISTORY 和 WAREHOUSE_EVENTS_HISTORY。它们分别回答“花了多少”“谁花的”“为什么花”。

WAREHOUSE_METERING_HISTORY 是成本计量的基石。它按仓库、按小时记录信用点消耗,关键字段包括:WAREHOUSE_NAME(仓库名)、START_TIME/END_TIME(计量窗口)、CREDITS_USED(消耗的信用点)、CREDITS_USED_COMPUTE(计算信用点)、CREDITS_USED_CLOUD_SERVICES(云服务信用点)。注意:CREDITS_USED 是计算与云服务之和,做成本分析时通常要拆开看,因为云服务信用点往往不直接对应仓库运行。

QUERY_HISTORY 回答“谁在花钱”。在 ACCOUNT_USAGE 中,它记录每条查询的 QUERY_ID、QUERY_TEXT、USER_NAME、WAREHOUSE_NAME、WAREHOUSE_SIZE、EXECUTION_STATUS、TOTAL_ELAPSED_TIME、CREDITS_USED_CLOUD_SERVICES 等。其中 QUERY_ID 是连接查询与计量的关键纽带,但要注意:QUERY_HISTORY 本身不直接给出该查询消耗的信用点,需要结合仓库运行时长和仓库规格间接估算。

WAREHOUSE_EVENTS_HISTORY 记录仓库的启停、扩缩容事件,字段包括 WAREHOUSE_NAME、EVENT_NAME(如 RESUME、SUSPEND、SCALE_UP)、EVENT_TIME、CLUSTER_NUMBER。它解释了“为什么这个小时信用点突然升高”——可能是自动扩缩容触发了多集群,也可能是仓库被意外唤醒。

表之间的关联关系

这三张表通过 WAREHOUSE_NAME 和 START_TIME 时间窗口关联。典型的分摊逻辑是:以 WAREHOUSE_METERING_HISTORY 的每小时信用点为“总池”,用 QUERY_HISTORY 中同一仓库、同一时间窗口内的查询执行时长占比,把信用点分摊到具体查询和用户。WAREHOUSE_EVENTS_HISTORY 则用于解释异常波动,比如某小时信用点翻倍,是因为发生了 SCALE_UP 事件。

Snowflake 成本可观测性视图体系与关联关系 ACCOUNT_USAGE(账户级 · 历史 · 延迟 45min~3h) WAREHOUSE_METERING_HISTORY WAREHOUSE_NAME · START_TIME · END_TIME CREDITS_USED · CREDITS_USED_COMPUTE CREDITS_USED_CLOUD_SERVICES → 成本计量的“总池” QUERY_HISTORY QUERY_ID · USER_NAME · WAREHOUSE_NAME WAREHOUSE_SIZE · EXECUTION_STATUS TOTAL_ELAPSED_TIME · QUERY_TEXT → 谁在花钱、花了多久 WAREHOUSE_EVENTS_HISTORY WAREHOUSE_NAME · EVENT_NAME EVENT_TIME · CLUSTER_NUMBER RESUME / SUSPEND / SCALE_UP → 为什么成本突然波动 INFORMATION_SCHEMA(数据库级 · 实时 · 保留 7~14 天) QUERY_HISTORY(数据库级) QUERY_ID · USER_NAME · WAREHOUSE_NAME EXECUTION_STATUS · TOTAL_ELAPSED_TIME START_TIME · END_TIME → 近实时排障与短期追踪 WAREHOUSE_METERING_HISTORY (数据库级,仅当前数据库上下文) WAREHOUSE_NAME · CREDITS_USED START_TIME · END_TIME → 低延迟用量观察 TABLES / COLUMNS / STAGES 等 对象元数据 · 存储占用线索 TABLE_NAME · ROW_COUNT · BYTES CREATED · LAST_ALTERED → 存储成本辅助分析 同名字段 QUERY_ID 关联 WAREHOUSE_NAME 关联键:WAREHOUSE_NAME + 时间窗口(START_TIME/END_TIME)→ 将计量信用点分摊到查询与用户

实际查询示例:把信用点分摊到用户

下面这段 SQL 演示如何用 ACCOUNT_USAGE 把某仓库某小时的信用点,按查询执行时长占比分摊到用户。这是成本分摊模型的最小可用版本:

WITH meter AS (
  SELECT WAREHOUSE_NAME,
         DATE_TRUNC('hour', START_TIME) AS hr,
         SUM(CREDITS_USED_COMPUTE) AS total_credits
  FROM SNOWFLAKE.ACCOUNT_USAGE.WAREHOUSE_METERING_HISTORY
  WHERE START_TIME >= DATEADD('day', -1, CURRENT_TIMESTAMP())
  GROUP BY 1, 2
),
q AS (
  SELECT WAREHOUSE_NAME,
         DATE_TRUNC('hour', START_TIME) AS hr,
         USER_NAME,
         SUM(TOTAL_ELAPSED_TIME) AS user_elapsed
  FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
  WHERE START_TIME >= DATEADD('day', -1, CURRENT_TIMESTAMP())
    AND EXECUTION_STATUS = 'SUCCESS'
  GROUP BY 1, 2, 3
),
total AS (
  SELECT hr, WAREHOUSE_NAME, SUM(user_elapsed) AS all_elapsed
  FROM q GROUP BY 1, 2
)
SELECT q.hr, q.WAREHOUSE_NAME, q.USER_NAME,
       ROUND(m.total_credits * q.user_elapsed / NULLIF(t.all_elapsed,0), 4) AS allocated_credits
FROM q
JOIN total t ON q.hr = t.hr AND q.WAREHOUSE_NAME = t.WAREHOUSE_NAME
JOIN meter m ON q.hr = m.hr AND q.WAREHOUSE_NAME = m.WAREHOUSE_NAME
ORDER BY allocated_credits DESC;

这段查询的关键判断点:EXECUTION_STATUS = 'SUCCESS' 过滤掉失败查询,避免把无效执行计入分摊;NULLIF(t.all_elapsed,0) 防止除零;CREDITS_USED_COMPUTE 而非 CREDITS_USED,因为云服务信用点不应按查询时长分摊。运行后如果某用户分摊信用点异常高,再回到 QUERY_HISTORY 查看其 QUERY_TEXT 和 WAREHOUSE_SIZE,判断是查询本身昂贵还是仓库规格过大。

延迟与保留期对选型的影响

选择视图时,必须把延迟和保留期作为硬约束。做月度成本报告,用 ACCOUNT_USAGE,因为数据完整、保留 365 天;做实时仓库异常告警,用 INFORMATION_SCHEMA,因为 ACCOUNT_USAGE 的延迟会让告警滞后数小时,失去意义;做跨数据库的全局分摊,只能用 ACCOUNT_USAGE,因为 INFORMATION_SCHEMA 被限制在单个数据库内。

常见误区:直接用 INFORMATION_SCHEMA.QUERY_HISTORY 做长期成本趋势,结果发现数据只保留 7 天,历史全部丢失。长期分析必须落到 ACCOUNT_USAGE 或自建持久化表。

建立成本可观测性的最小闭环

一个可落地的做法是:每天定时把 ACCOUNT_USAGE 的 WAREHOUSE_METERING_HISTORY 和 QUERY_HISTORY 增量抽取到自建的 FINOps 数据库,按天分区存储。这样既绕开了 ACCOUNT_USAGE 的查询延迟和并发限制,又能保留超过 365 天的历史,还能自由关联内部的组织架构、项目标签。抽取时以 START_TIME 为水位线,每次只拉取最近 2 小时的数据做幂等覆盖,避免重复。抽取完成后,用 WAREHOUSE_EVENTS_HISTORY 做异常标注,把 SCALE_UP、RESUME 事件与信用点峰值对齐,形成“成本波动—事件解释”的对照表。

至此,成本可观测性的数据底座就搭好了:ACCOUNT_USAGE 提供权威的历史计量,INFORMATION_SCHEMA 提供近实时的局部视图,三张核心表通过仓库名和时间窗口关联,支撑起分摊、归因和异常解释三类分析。后续的预算、告警和优化,都建立在这套视图体系之上。