如何在 Snowflake 中按不同功能拆分 billing?
结论
如果需要清楚核算并限制不同业务功能的计算费用,建议为每项功能分配独立的 virtual warehouse,再按需为各 warehouse 配置 resource monitor。
Snowflake 无法将 warehouse 的计算费用直接绑定到某个 database 或 schema。查询产生的计算消耗记在执行该查询的 warehouse 上,而不是数据对象所属的 database 或 schema 上。此外,一条查询可能同时访问多个 database 或 schema,无法直接按照对象边界拆分计算费用。
resource monitor 可以监控和限制 credit 消耗,但不会自动拆分 Snowflake 账单。实际核算通常需要结合以下方式:
- 使用独立 warehouse,建立清晰的计算成本边界。
- 使用
QUERY_TAG标记业务、功能、团队或项目。 - 通过
SNOWFLAKE.ACCOUNT_USAGE生成内部成本报表。 - 使用 object tags、budgets 等功能管理成本归属和预算。具体能否使用,取决于账户版本、授权情况以及 Snowflake 当前提供的功能。
推荐方案:按功能拆分 warehouse
可以让 ETL、BI 查询和数据科学工作负载分别使用不同的 warehouse:
CREATE WAREHOUSE ETL_WH
WAREHOUSE_SIZE = 'MEDIUM'
AUTO_SUSPEND = 60
AUTO_RESUME = TRUE
INITIALLY_SUSPENDED = TRUE;
CREATE WAREHOUSE BI_WH
WAREHOUSE_SIZE = 'SMALL'
AUTO_SUSPEND = 60
AUTO_RESUME = TRUE
INITIALLY_SUSPENDED = TRUE;
CREATE WAREHOUSE DS_WH
WAREHOUSE_SIZE = 'LARGE'
AUTO_SUSPEND = 300
AUTO_RESUME = TRUE
INITIALLY_SUSPENDED = TRUE;
再通过角色权限控制各团队能够使用的 warehouse:
GRANT USAGE ON WAREHOUSE ETL_WH TO ROLE ETL_ROLE;
GRANT USAGE ON WAREHOUSE BI_WH TO ROLE BI_ROLE;
GRANT USAGE ON WAREHOUSE DS_WH TO ROLE DATA_SCIENCE_ROLE;
这样便可以根据 warehouse 的计量记录核算费用:
SELECT
warehouse_name,
SUM(credits_used_compute) AS compute_credits,
SUM(credits_used_cloud_services) AS cloud_services_credits,
SUM(credits_used) AS total_credits
FROM snowflake.account_usage.warehouse_metering_history
WHERE start_time >= DATEADD('month', -1, CURRENT_TIMESTAMP())
GROUP BY warehouse_name
ORDER BY total_credits DESC;
ACCOUNT_USAGE 视图的数据可能有延迟,不适合用作完全实时的用量控制机制。
使用 resource monitor 控制额度
不同的 warehouse 可以设置各自的额度。例如,为 BI warehouse 设置每月 credit 配额:
CREATE RESOURCE MONITOR BI_MONTHLY_MONITOR
WITH CREDIT_QUOTA = 500
FREQUENCY = MONTHLY
START_TIMESTAMP = IMMEDIATELY
TRIGGERS
ON 75 PERCENT DO NOTIFY
ON 90 PERCENT DO SUSPEND
ON 100 PERCENT DO SUSPEND_IMMEDIATE;
ALTER WAREHOUSE BI_WH
SET RESOURCE_MONITOR = BI_MONTHLY_MONITOR;
resource monitor 主要用于用户管理的 virtual warehouse。Snowflake 的部分 serverless 功能、存储费用及其他平台服务,并不会全部受到同一配额限制。
SUSPEND 和 SUSPEND_IMMEDIATE 会影响正在运行或之后提交的工作负载。在生产环境中设置这些阈值时要格外谨慎,以免关键任务意外中断。
无法拆分 warehouse 时使用 QUERY_TAG
如果多个功能必须共用一个 warehouse,可以为会话或查询添加业务标签:
ALTER SESSION SET QUERY_TAG = 'function=finance_reporting';
SELECT *
FROM analytics.finance.monthly_report;
应用程序也可以在执行任务前设置标签:
ALTER SESSION SET QUERY_TAG = 'function=customer_sync;team=crm';
之后可以按标签统计查询活动:
SELECT
query_tag,
warehouse_name,
COUNT(*) AS query_count,
SUM(total_elapsed_time) / 1000 AS elapsed_seconds,
SUM(bytes_scanned) AS bytes_scanned
FROM snowflake.account_usage.query_history
WHERE start_time >= DATEADD('month', -1, CURRENT_TIMESTAMP())
GROUP BY query_tag, warehouse_name
ORDER BY elapsed_seconds DESC;
不过,QUERY_HISTORY 中的运行时间和扫描字节数等指标,并不等于精确的 credit 消耗。warehouse 的费用取决于运行时间和规格,多个查询还可能并发执行。如果要在共享 warehouse 内部分摊成本,需要提前制定内部规则,例如按照查询执行时间、负载时间或扫描量进行分配。由此得到的是成本估算,并非 Snowflake 原生账单明细。
database 和 schema 能做什么
database 和 schema 适合划分以下内容:
- 数据所有权;
- 访问权限;
- 生命周期和保留策略;
- 存储量统计;
- 对象标签与成本归属元数据。
但它们无法直接限制 warehouse 上运行的查询所消耗的 credits。例如,查询 SALES_DB 中的数据时,计算费用仍会计入当前使用的 warehouse:
USE WAREHOUSE BI_WH;
USE DATABASE SALES_DB;
USE SCHEMA REPORTING;
SELECT * FROM MONTHLY_SALES;
这次查询的计算消耗属于 BI_WH,不会自动记到 SALES_DB 或 REPORTING schema 名下。
存储成本可以根据 database 或 schema 中对象的占用量另行分析,但还要考虑 Time Travel、Fail-safe、克隆、暂存区和数据共享等因素。计算成本与存储成本应分别核算。
还需要单独考虑的费用
只按 warehouse 拆分,无法覆盖 Snowflake 的全部费用。完整的成本模型通常还要包括:
- 数据存储;
- cloud services;
- serverless 功能;
- automatic clustering;
- Snowpipe;
- materialized view maintenance;
- search optimization;
- replication 和跨区域数据传输。
这些项目对应的用量来源和计量视图各不相同,也不一定受 resource monitor 控制。如果某项功能由多个团队共用,可以借助相应的 usage view、对象标签或事先约定的规则分摊费用。
实际使用时,可以采用两层方案:先用独立 warehouse 建立可审计的计算成本边界,再用 QUERY_TAG 标记具体应用或任务。database 和 schema 更适合数据治理及存储归属,不应作为拆分 warehouse 计算费用的主要依据。
备注:内容仅供参考。
