元数据模型:技术元数据、业务元数据、操作元数据
搞数据治理这么久,我见过太多团队一上来就建模型,结果建出来的东西没人用。你想想看,元数据模型要是跟业务对不上号,那就是个空壳子。今天咱们把这三大类拆开来聊。
先问个问题:什么是好的元数据模型?我个人习惯把它看作三层楼——技术层、业务层、操作层。每层解决不同的问题,但加在一起才能把管道的全貌看清楚。
技术元数据:管道的骨架
说白了,技术元数据就是描述数据「长什么样」的信息。它包括数据库表结构、字段类型、分区信息、ETL 脚本、存储路径这些东西。
- 表名、列名、数据类型、长度约束
- 主键与外键关系
- 索引、分区键、分桶策略
- 存储格式(Parquet、ORC、Avro)
- ETL 脚本、任务依赖
我刚开始做数据治理时,遇到最头疼的事就是脚本依赖一团乱。一次上线改了个表的字段类型,下游十几个任务全挂了。
看看我们怎么抓取技术元数据。从 Hive 表来举个例子:
DESCRIBE FORMATTED dwd.user_order_daily;
-- 输出示例
+----------------------+--------------------------+---------+
| col_name | data_type | comment |
+----------------------+--------------------------+---------+
| user_id | bigint | 用户ID |
| order_id | bigint | 订单ID |
| order_amount | decimal(18,2) | 订单金额 |
| order_status | int | 订单状态 |
| create_time | timestamp | 创建时间 |
+----------------------+--------------------------+---------+
# Partition Information
# col_name data_type comment
+----------------------+--------------------------+---------+
| dt | string | 分区日期 |
+----------------------+--------------------------+---------+
# Storage Information
SerDe Library: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
InputFormat: org.apache.hadoop.mapred.TextInputFormat
OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
Compressed: No
Num Buckets: -1
Bucket Columns: []
Sort Columns: []
Storage Desc Params:
serialization.format 1
抓元数据时,我建议你同时采集完整的数据血缘分。血缘分不清,排查问题就像大海捞针。我曾经踩过这个坑——某个报表数据对不上,折腾了两天才发现是上游一个临时表改了逻辑。
业务元数据:管道的灵魂
光有技术元数据,你知道字段叫什么,但不知道它「代表什么」。这就是业务元数据要解决的问题。
业务元数据重点包括:
- 业务术语表——比如「活跃用户」的定义是什么?30天内登录一次?还是7天内?
- 数据质量规则——比如金额字段不能为负、用户ID必须在用户表存在
- 数据安全等级——哪些字段属于敏感信息?PII数据如何脱敏?
- 数据地图与血缘——哪张表对应业务哪个环节?
- 指标口径说明——GMV是怎么算的?包含退款订单吗?
血的教训:有个项目,技术团队跟业务团队对「新客」的理解完全不一样。技术台账认为只要没下过单就算新客;业务说注册当天就算新客。由于在元数据模型中没有统一字段定义,最终报表对不上数,废了三天时间重新对齐。
业务元数据的采集,通常从数据词典和指标系统入手。拿我们团队的配置来说,会在治理平台里维护一份业务术语表:
{
"business_terms": [
{
"term_name": "活跃用户",
"term_id": "BT-001",
"definition": "最近30天内有登录行为的去重用户数",
"domain": "用户增长",
"owner": "张三",
"approval_status": "已发布",
"related_fields": ["dwd.user_login.dt", "dwd.user_login.user_id"]
},
{
"term_name": "GMV",
"term_id": "BT-002",
"definition": "用户已支付订单的总金额,含退款订单按正数计入",
"domain": "交易分析",
"owner": "李四",
"approval_status": "已发布",
"related_fields": ["dwd.order_daily.order_amount", "dwd.order_daily.order_status"]
}
]
}
别小看这个配置表。有了它,新来的分析师可以快速理解数据,不用到处问人。我每次做数据治理项目,第一件事就是拉着业务方把术语表过一遍,你想想看,这块搞不定,后面全是虚的。
操作元数据:管道的脉搏
操作元数据是关于「运行状态」的信息。管道跑了吗?跑成功了吗?跑多久?有多少行?报错了吗?
我通常会把它分成几类:
| 类别 | 内容 | 示例 |
|---|---|---|
| 作业运行 | 任务开始/结束时间、执行状态 | ETL作业2024-01-15 08:00:00 开始,08:15:32 完成 |
| 数据质量 | 校验结果、异常规则命中数 | 字段order_amount空值率超过阈值(5%) |
| 数据量指标 | 插入行数、更新行数、文件大小 | 今天写入1,234,567行,比昨日增长8% |
| 错误日志 | 异常堆栈、失败原因 | Java.lang.OutOfMemoryError 导致任务失败 |
| 性能统计 | CPU使用率、内存瓶颈、I/O | Shuffle阶段CPU使用率持续95% |
操作元数据怎么采集?最常见的方式是在作业框架里埋点。比如我处理过的一个 Spark 任务,会在完成后把运行信息写到一张审计表:
INSERT INTO meta.operation_log (
task_name,
run_date,
start_time,
end_time,
status,
rows_inserted,
error_msg
)
VALUES (
'dwd_user_order_daily',
'2024-01-15',
'2024-01-15 08:00:00',
'2024-01-15 08:15:32',
'SUCCESS',
1234567,
NULL
);
- 近30天:保留完整明细
- 30天到1年:聚合到小时级粒度
- 超过1年:只存成功/失败计数,用于长期趋势分析
三类元数据的协同关系
我遇到很多新手会问:这三类元数据是不是分开维护?不,它们必须在一个模型里协同工作。
举个例子,你在排查数据异常时:
- 用业务元数据确认指标口径(这个GMV为什么比预估低?)
- 用技术元数据找到对应的表和字段(订单金额来自哪张表?)
- 用操作元数据检查当天的管道运行情况(作业有没有失败?数据有没有丢失?)
我个人习惯在治理平台的元数据模型里,为每个数据资产都挂载三类标签。比如一张订单明细表,除了技术信息,还要关联业务术语、运行记录。这样一次查询就能拿到完整上下文,效率翻倍。
模型的落地实践建议
好,说了这么多理论,来点实际的。我一般按这个步骤做:
- 先盘点后建模——不要闭门造车,先拉出所有已有数据资产
- 从技术元数据入手——最简单,用工具批量采集,两天搞定
- 逐步补齐业务信息——拉上业务方,每周两个领域地过术语
- 操作元数据要自底向上——从最频繁报错的作业开始收割
- 测试血缘链路的完整性——从报表反查到源数据,确保每跳都有记录
避坑指南:我曾经一口气把整个数据湖所有表和字段的元数据全部采集到位,结果一百多页的模型文档没人看。后来学乖了——业务元数据要按使用频率分级,常用字段优先标注。你想想看,没人关心的冷门表,标注再完整也没用。
三类元数据的关系可以用一张图呈现,我把它画成三个相互重叠的环,每个环都有自己的核心内容,交叉区域才是元数据治理的价值所在。
你看这个三层环,每个圆都有自己聚焦的内容,但中间的交集才是元数据治理真正发挥作用的地方。技术元数据告诉我们数据在哪、长什么样;业务元数据解释它有什么含义、应该怎么用;操作元数据告诉我们它今天有没有好好运行。
三个环缺一不可。光有技术和操作,你只能看到管道在转但不知道转什么;光有业务和操作,你找不到对应的实际数据在哪;光有技术和业务,你没法知道数据今天是不是可靠的。
嗯,这里要注意:不同团队对三层元数据的侧重点不同。数据平台团队更关注技术元数据,数据分析团队更关注业务元数据,运维团队更关注操作元数据。但我一直跟人讲,不管你是哪个角色,最后都要看懂这三层打通之后的全景图。