2. Snowflake平台架构与机器学习集成基础
要在 Snowflake 上做机器学习,先要理解它的架构为什么和传统数据库不一样。Snowflake 是云原生架构,核心特征是存储与计算分离:数据持久化在云对象存储(如 AWS S3、Azure Blob、GCS)中,由 Snowflake 统一管理成微分区(micro-partition);而计算能力由独立的虚拟仓库(Virtual Warehouse)提供,按需创建、按秒计费、可随时扩缩。这种分离意味着:存储层是所有计算共享的同一份数据,计算层则是可以并行存在、互不干扰的多组资源。
对机器学习工作负载来说,这个架构带来三个直接后果。第一,特征工程、模型训练、批量推理可以各自使用不同的虚拟仓库,互不抢占资源;第二,数据共享(Data Sharing)让特征表可以在不复制数据的前提下跨账户使用,这对跨团队协作建模非常关键;第三,计算资源可以按工作负载特征选择规格——训练用大仓库,推理用小仓库,避免资源浪费。
存储计算分离对机器学习的具体影响
存储计算分离不是一句抽象口号,它直接决定了机器学习任务该怎么组织。假设你有一个电商场景:需要从订单表、用户行为日志、商品维表中构建特征,训练一个购买意向预测模型,然后对全量用户做批量打分。在传统数仓中,特征工程和训练往往争抢同一套计算资源,训练任务一跑,报表查询就变慢。在 Snowflake 中,你可以这样分配:
- 特征工程使用
WH_FEATURE(LARGE),执行 Snowpark DataFrame 转换,把原始表聚合成宽表ML_FEATURES.USER_INTENT; - 模型训练使用
WH_TRAIN(XLARGE),通过 Snowpark ML 的XGBClassifier在特征宽表上训练,训练过程不占用 BI 仓库; - 批量推理使用
WH_INFER(MEDIUM),把训练好的模型注册为 UDF,对全量用户表调用PREDICT函数生成打分结果; - BI 看板继续使用
WH_BI(SMALL),查询不受训练任务影响。
这里的关键判断依据是:每个虚拟仓库有独立的 credit 消耗曲线。你可以在 ACCOUNT_USAGE.WAREHOUSE_METERING_HISTORY 中按仓库名查看每小时消耗,如果发现 WH_TRAIN 在非训练时段仍有消耗,说明有会话未关闭或自动挂起设置过长。典型的优化是把 AUTO_SUSPEND 设为 60 秒,AUTO_RESUME 设为 TRUE,让仓库在空闲时自动释放。
虚拟仓库规格与机器学习任务的匹配
虚拟仓库的规格从 XSMALL 到 6XLARGE,主要影响 CPU 核数和内存。对机器学习任务来说,规格选择不是越大越好,而是要看瓶颈在哪里。特征工程通常是 I/O 密集和 SQL 聚合密集,LARGE 到 XLARGE 足够;模型训练如果是单机内存型算法(如 scikit-learn 风格),XLARGE 能提供更多内存,但如果是 Snowpark ML 的分布式训练,则需要关注仓库的并行度是否匹配数据分区数;批量推理是典型的吞吐型任务,MEDIUM 到 LARGE 配合多集群(Multi-cluster Warehouse)可以水平扩展。
QUERY_HISTORY 中的 BYTES_SCANNED、PARTITIONS_SCANNED 和 EXECUTION_TIME 判断瓶颈。如果 PARTITIONS_SCANNED 远大于 PARTITIONS_TOTAL,说明微分区裁剪效果差,应先优化聚簇键而不是盲目扩大仓库。
数据共享与机器学习协作
Snowflake 的数据共享(Data Sharing)允许提供方把数据库、模式或表共享给消费方账户,消费方直接查询共享数据,不需要复制。对机器学习来说,这解决了一个长期痛点:特征表往往由数据工程团队维护,模型团队需要频繁读取。传统做法是导出 CSV 或同步到另一个存储,既慢又容易不一致。使用共享后,模型团队在自己的账户中就能看到 SHARED_FEATURES.PUBLIC.USER_INTENT,直接用于训练。
但要注意,共享数据是只读的,消费方不能修改。如果模型团队需要在共享特征基础上做二次加工,应该在自己的账户中创建派生表,并明确标注数据血缘。另外,共享不消耗提供方的计算资源,消费方用自己的虚拟仓库查询,这一点对成本分摊很重要。
一个可执行的最小示例
下面给出一个从特征构建到批量推理的最小可执行流程,假设已有 RAW.ORDERS 和 RAW.USERS 两张表:
-- 1. 创建特征工程仓库
CREATE OR REPLACE WAREHOUSE WH_FEATURE
WAREHOUSE_SIZE = 'LARGE'
AUTO_SUSPEND = 60
AUTO_RESUME = TRUE;
-- 2. 构建特征宽表
CREATE OR REPLACE TABLE ML_FEATURES.USER_INTENT AS
SELECT
u.user_id,
COUNT(o.order_id) AS order_cnt_30d,
SUM(o.amount) AS total_amount_30d,
DATEDIFF('day', MAX(o.order_date), CURRENT_DATE()) AS days_since_last_order,
CASE WHEN COUNT(o.order_id) > 0 THEN 1 ELSE 0 END AS label_purchase
FROM RAW.USERS u
LEFT JOIN RAW.ORDERS o
ON u.user_id = o.user_id
AND o.order_date >= DATEADD('day', -30, CURRENT_DATE())
GROUP BY u.user_id;
-- 3. 训练仓库(在 Snowpark ML 中执行)
-- 使用 WH_TRAIN (XLARGE),代码略,核心是读取上表并训练 XGBoost
-- 4. 批量推理:注册模型为 UDF 后调用
SELECT
user_id,
ML_PREDICT(model_intent, order_cnt_30d, total_amount_30d, days_since_last_order) AS score
FROM ML_FEATURES.USER_INTENT;
执行后,观察 WH_INFER 的查询历史,如果 EXECUTION_TIME 随用户量线性增长,说明需要扩大仓库或启用多集群;如果 COMPILATION_TIME 占比高,则说明 UDF 初始化开销大,可以考虑把模型加载改为会话级缓存。这些判断都依赖对虚拟仓库和查询历史的持续观察,而不是一次性配置。
架构关系总结
把上面的内容串起来:存储层提供统一、共享、可回溯的数据底座;计算层的虚拟仓库按工作负载隔离资源;数据共享让特征表跨账户流动而不复制;机器学习工作负载则分别落在特征工程、训练、推理三个环节,各自匹配不同规格的仓库。理解这四层关系,才能在 Snowflake 上设计出既高效又可控的机器学习流水线。