3. 数据层架构设计

在 Databricks 机器学习平台中,数据层不是简单的“存表”问题,而是决定特征可复用性、训练可复现性与线上推理一致性的基础。一个生产级数据层通常由三层能力叠加而成:Delta Lake 负责存储格式与事务语义,Unity Catalog 负责跨工作区的统一元数据、权限与血缘,特征表(Feature Store) 负责把离线特征与在线特征组织成可被训练和推理共同消费的资产。三者不是并列关系,而是“存储底座—治理平面—特征接口”的纵向分工。

Delta Lake:把数据湖变成可事务的表

Delta Lake 的核心价值在于用 _delta_log 事务日志为 Parquet 数据文件加上 ACID 能力。每次写入都会生成一个新的 JSON 提交,记录新增/删除的文件、schema 变化和统计信息。读取时先解析日志得到某个版本的文件清单,再扫描对应 Parquet 文件,因此可以做到快照隔离、时间旅行和并发写入冲突检测。

对特征工程而言,最常用的三个能力是:

  • MERGE 增量更新:按主键把新批次特征合并进特征表,避免全量重写。
  • 时间旅行:用 VERSION AS OF 或 TIMESTAMP AS OF 复现某次训练所用的特征快照。
  • OPTIMIZE / Z-ORDER:合并小文件并按查询高频列聚簇,降低点查与范围扫描成本。

一个典型的特征表建表与增量写入可以写成:

CREATE TABLE IF NOT EXISTS ml_prod.features.user_behavior (
  user_id        BIGINT,
  feature_ts     TIMESTAMP,
  click_cnt_7d   INT,
  order_amt_30d  DECIMAL(18,2),
  last_login_gap DOUBLE
)
USING DELTA
PARTITIONED BY (DATE(feature_ts))
TBLPROPERTIES (
  'delta.autoOptimize.optimizeWrite' = 'true',
  'delta.autoOptimize.autoCompact'   = 'true'
);

MERGE INTO ml_prod.features.user_behavior AS t
USING ml_stage.features.user_behavior_inc AS s
ON t.user_id = s.user_id AND t.feature_ts = s.feature_ts
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;

这里 feature_ts 是特征的计算时间,而不是写入时间,它决定了后续 point-in-time 关联的正确性。分区键选择 DATE(feature_ts) 是为了让按天回溯和按天清理都变成分区裁剪操作。

Unity Catalog:三层命名空间与统一治理

Unity Catalog 把对象组织为 catalog.schema.table 三层命名空间,并在此之上提供权限、血缘、标签和跨工作区访问。对机器学习数据层来说,它解决三个具体问题:

  • 命名空间隔离:用 ml_dev、ml_stage、ml_prod 三个 catalog 区分环境,避免开发表被误用于生产训练。
  • 权限收敛:特征表通常只允许特征平台服务账号写入,训练与推理角色只读,权限通过 GRANT SELECT ON TABLE 授予。
  • 血缘追踪:从原始事件表到特征表再到模型,Unity Catalog 自动记录表级与列级血缘,便于定位特征漂移来源。

一个可落地的权限与标签示例:

GRANT USE CATALOG ON CATALOG ml_prod TO `ml-trainer`;
GRANT USE SCHEMA  ON SCHEMA  ml_prod.features TO `ml-trainer`;
GRANT SELECT      ON TABLE   ml_prod.features.user_behavior TO `ml-trainer`;

ALTER TABLE ml_prod.features.user_behavior
SET TAGS ('domain' = 'user', 'owner' = 'feature-platform', 'sla' = 'daily-06:00');

标签不是装饰,它让特征检索、成本归因和 SLA 监控可以按 domain 或 owner 聚合。当特征数量增长到数百张表时,没有标签体系几乎无法治理。

特征表:离线与在线的一致组织

Databricks 特征表在 Delta 表之上增加了特征元数据与在线存储同步能力。其数据组织通常包含三部分:

  1. 主键:如 user_id,用于在线点查。
  2. 时间戳键:如 feature_ts,用于离线 point-in-time 关联,防止标签泄漏。
  3. 特征列:如 click_cnt_7d、order_amt_30d,需带明确的类型与默认值。

离线训练时,用 create_training_set 按标签时间戳关联特征快照;在线推理时,特征表把最新版本同步到在线存储(如 DynamoDB、Cosmos DB 或在线 Delta 表),由模型服务按主键读取。关键约束是:离线与在线必须来自同一份特征定义,否则会出现训练-服务偏差。

特征表的时间戳键必须早于标签时间戳,且关联时使用“小于等于标签时间”的最近一条特征,这是避免标签泄漏的标准做法。

三层协同的数据流

把三者串起来看,数据从原始事件进入 Delta 表,经特征计算写入特征表,由 Unity Catalog 统一登记与授权,训练和推理分别从离线快照与在线存储读取。下图展示了这一纵向结构与关键接口。

数据层纵向结构:存储底座 · 治理平面 · 特征接口 Delta Lake(存储与事务) 原始事件表 events_raw 特征计算表 features_delta 事务日志 _delta_log 时间旅行 / OPTIMIZE VERSION AS OF Unity Catalog(治理平面) 三层命名空间 catalog.schema.table 权限 GRANT SELECT / USE 血缘追踪 表级 / 列级 标签 TAGS domain / owner / sla 特征表(离线 / 在线一致接口) 离线特征快照 point-in-time 关联 create_training_set 防标签泄漏 在线特征存储 按主键点查 低延迟读取 与离线同定义 消费方 训练作业 模型服务 批量打分 训练集 在线查询 推理请求

数据组织中的关键参数与判断依据

在真实项目中,数据层是否健康可以通过几个可观测点判断:

观察项合理范围(示例)异常含义
特征表小文件数单分区 < 50 个写入过碎,需 OPTIMIZE
离线/在线特征差异率< 0.1%存在训练-服务偏差
特征新鲜度延迟≤ SLA 窗口上游计算或同步失败
无标签泄漏校验feature_ts ≤ label_ts关联逻辑错误

这些指标应写入特征表的标签或监控表,由 Unity Catalog 的标签体系聚合,而不是散落在各团队的脚本里。数据层架构设计的最终目标,是让“同一份特征定义”在离线训练与在线推理之间保持可验证的一致性,同时让权限、血缘和成本都能被统一治理。