2. 数据资产元数据采集:元数据模型设计、采集策略与频率、增量与全量采集
元数据采集,说白了就是给数据资产做「人口普查」。你连自己家里有多少张表、字段是什么类型、数据从哪里来都不知道,后面做热度分析就是空中楼阁。我在好几个项目里都见过这种情况——业务方问「这张表到底谁在用?」,平台方答不上来,因为元数据压根没采全。
这一章,我们就来聊聊怎么把元数据「采好」。核心就三件事:模型怎么设计、策略怎么定、增量全量怎么配合。
2.1 元数据模型设计:先搭骨架,再填肉
我个人习惯,设计元数据模型时先想清楚三个层次:
- 技术元数据:库、表、字段、分区、存储路径、文件格式、数据量。
- 业务元数据:字段中文名、业务定义、数据域、所属流程、负责人。
- 操作元数据:ETL 作业、调度时间、血缘关系、访问日志、变更记录。
你想想看,如果只采技术元数据,你只能知道「有张表叫 dwd_order_di」,但不知道它对应哪个业务订单、谁负责维护。反过来,只采业务元数据,你又没法做技术层面的热度计算。所以,三者缺一不可。
下面是我在项目中常用的一套核心模型结构,供你参考:
| 模型名称 | 核心字段 | 说明 |
|---|---|---|
| catalog_info | catalog_id, name, type, owner, create_time | 数据目录/库级信息 |
| schema_info | schema_id, catalog_id, name, description | 模式/命名空间 |
| table_info | table_id, schema_id, table_name, table_type, location, format, row_count, size_bytes | 表级元数据,核心实体 |
| column_info | column_id, table_id, column_name, data_type, comment, is_partition, ordinal_position | 字段级元数据 |
| partition_info | partition_id, table_id, partition_value, create_time, row_count | 分区信息,Hive/Iceberg 等场景必用 |
| etl_job_info | job_id, job_name, job_type, schedule_expr, source_table, target_table, last_run_time | ETL 作业元数据 |
| lineage_edge | edge_id, upstream_table, upstream_column, downstream_table, downstream_column, job_id | 血缘关系边 |
| access_log | log_id, table_id, user, query_type, query_time, duration_ms, engine | 访问日志,热度计算的核心输入 |
关键原则:模型设计要「够用但不过度」。我曾经在一个项目里把元数据模型拆到了 30 多张表,结果采集链路太长,数据还没采完,业务方已经下班了。后来精简到 8 张核心表,反而跑得又快又稳。
2.2 采集策略与频率:不是所有数据都需要秒级刷新
元数据采集最忌讳「一刀切」。不同元数据的变更频率天差地别——表结构可能一个月改一次,访问日志每秒都在产生。你如果都用同一套频率去采,要么浪费资源,要么数据滞后。
我建议按变更频率把元数据分成三类:
- 静态元数据(低频变更):库、表、字段结构。这类数据通常只在 DDL 操作时变化,一天采一次全量就够了。
- 半静态元数据(中频变更):分区信息、数据量、文件数。每次数据写入后都会变,建议每小时或每批次结束后采集。
- 动态元数据(高频变更):访问日志、查询记录、作业运行状态。这类数据需要实时或准实时采集,延迟控制在分钟级。
下面是我在项目中常用的采集频率配置:
| 元数据类型 | 采集频率 | 采集方式 | 典型数据源 |
|---|---|---|---|
| 表结构/字段 | 每天 1 次(凌晨) | 全量 | Hive Metastore, MySQL Information Schema |
| 分区信息 | 每小时 1 次 | 增量 | Hive Metastore, Iceberg/REST Catalog |
| 数据量/行数 | 每批次结束后 | 增量 | Spark/Hive ANALYZE TABLE, 文件系统 |
| 访问日志 | 实时(Kafka 流式) | 增量 | Hive/Spark Audit Log, Presto/Trino Query Log |
| ETL 作业状态 | 每 5 分钟 | 增量 | 调度系统 API (Airflow/DolphinScheduler) |
| 血缘关系 | 每天 1 次 | 全量+增量 | SQL Parser, Atlas Hook, DataHub |
我的经验:访问日志的采集一定要走消息队列,别直接查数据库。我曾经见过有人用 JDBC 轮询 Presto 的查询日志表,结果把 Presto Coordinator 查挂了,整个集群的查询都受影响。后来改成 Flume + Kafka 的流式采集,再也没出过问题。
2.3 增量与全量采集:双剑合璧
全量采集和增量采集不是二选一,而是配合使用。我习惯用一句话概括:「全量保底,增量提效」。
2.3.1 全量采集
全量采集就是把目标数据源的所有元数据全部拉一遍。优点是简单、完整、不会漏;缺点是慢、占资源、对源系统压力大。
适用场景:
- 首次初始化元数据仓库
- 数据源结构发生重大变更(如重建表)
- 增量采集出现数据不一致,需要全量修复
代码示例(伪代码,从 Hive Metastore 全量采集表信息):
def full_collect_tables(metastore_client):
"""全量采集所有表元数据"""
all_databases = metastore_client.get_all_databases()
all_tables = []
for db in all_databases:
tables = metastore_client.get_all_tables(db)
for table_name in tables:
table_info = metastore_client.get_table(db, table_name)
all_tables.append({
"database": db,
"table_name": table_name,
"create_time": table_info.createTime,
"last_access_time": table_info.lastAccessTime,
"table_type": table_info.tableType,
"location": table_info.sd.location,
"fields": [{"name": f.name, "type": f.type} for f in table_info.sd.cols]
})
return all_tables
2.3.2 增量采集
增量采集只拉取上次采集后发生变化的数据。优点是快、轻量、对源系统友好;缺点是需要可靠的变更捕获机制。
常见的增量采集方式:
- 时间戳对比:利用表的 create_time、update_time 字段,只拉取最近变更的数据。
- 事件监听:通过 Hook 或 Listener 捕获 DDL/DML 事件,实时推送变更。
- 日志解析:解析数据库的 Binlog、Audit Log,提取元数据变更。
- 版本号对比:利用元数据存储的版本号或序列号,只拉取高版本的数据。
代码示例(基于时间戳的增量采集):
def incremental_collect_tables(metastore_client, last_collect_time):
"""增量采集最近变更的表"""
# 假设 Metastore 支持按时间过滤
changed_tables = metastore_client.get_tables_changed_since(last_collect_time)
incremental_data = []
for table_ref in changed_tables:
table_info = metastore_client.get_table(table_ref.db, table_ref.name)
incremental_data.append({
"database": table_ref.db,
"table_name": table_ref.name,
"change_type": table_ref.change_type, # CREATE / ALTER / DROP
"change_time": table_ref.change_time,
"current_schema": [{"name": f.name, "type": f.type} for f in table_info.sd.cols]
})
return incremental_data
避坑指南:我曾经在一个项目里只用增量采集,结果某个表被重建了(DROP + CREATE),时间戳没变,增量采集完全没感知到。从那以后,我定了一个规矩:每周至少跑一次全量采集做数据对账,发现不一致就触发全量修复。
2.4 整体采集架构
下面这张图是我在项目中常用的元数据采集架构,你可以参考:
嗯,这张图基本概括了元数据采集的全链路。从数据源出发,经过全量/增量/事件/日志四种采集方式,统一进入 Kafka 消息队列,然后分别写入关系库(用于精确查询)和搜索引擎(用于全文检索和快速过滤),最后供给上层应用使用。
核心要点总结:
- 元数据模型要覆盖技术、业务、操作三个维度,8 张核心表足够起步
- 采集频率按变更频率分级,静态一天一次,动态实时采集
- 全量采集用于初始化和对账,增量采集用于日常变更捕获
- 访问日志必须走流式采集,别用 JDBC 轮询
- 每周至少一次全量对账,防止增量采集漏数据