3. 元数据采集与存储:手动采集 vs 自动采集、元数据存储模型

元数据管理这件事,说白了就两个核心动作:怎么把元数据弄进来,以及弄进来之后放哪儿。采集和存储,就像水管和水池——管子不通,水进不来;池子设计不好,水存不住也用不了。

这一章,我带你把这套「水管系统」和「水池结构」彻底捋清楚。

3.1 手动采集:最原始,但有时最管用

先说说手动采集。你可能觉得这都什么年代了,还手动?

嗯,我在项目中遇到过不少场景,自动采集反而搞不定。比如某个老系统,数据库是 Sybase ASE 12.5,连 JDBC 驱动都停产了。自动采集工具根本连不上。怎么办?只能让 DBA 把表结构导出成 SQL 脚本,我这边手动解析入库。

手动采集的典型场景包括:

  • 遗留系统:接口封闭、协议私有,自动工具无法接入
  • 外部数据源:供应商只提供 Excel 或 PDF 格式的元数据文档
  • 业务术语:业务口径、计算逻辑这类「人肉知识」,机器抓不到
  • 临时补录:自动采集遗漏或出错时,人工兜底
我的习惯:手动采集不是「手敲键盘」,而是用脚本半自动化。比如写个 Python 脚本读 Excel,再调 API 写入元数据平台。纯手工录入?那是给自己挖坑。

手动采集的优缺点很明显:

维度 手动采集 自动采集
准确性 高(人工校验) 中(依赖解析规则)
时效性 低(小时/天级) 高(分钟/秒级)
覆盖度 低(只能采集已知的) 高(全量扫描)
维护成本 高(人肉运维) 低(配置一次,持续运行)
适用场景 非结构化、封闭系统 标准化、开放接口

3.2 自动采集:数据架构师的「自动驾驶」

自动采集才是现代元数据管理的常态。你想想看,一个中型企业少说几百张表、几千个字段,靠人手工录?不现实。

自动采集的核心原理就四个字:协议适配。不同的数据源,用不同的协议去「扒」元数据。

  • 关系型数据库:通过 JDBC/ODBC 读取 information_schema
  • Hadoop 生态:通过 Hive Metastore API 或 Spark Catalog
  • 消息队列:通过 Schema Registry 获取 Avro/Protobuf 定义
  • ETL 工具:解析作业定义文件(XML/JSON)
  • BI 报表:通过 REST API 拉取报表元数据

避坑指南:我曾经在一个项目中,自动采集脚本每 5 分钟跑一次全量扫描,结果把生产库的 information_schema 表锁死了。后来改成增量采集 + 限流,才解决问题。记住:自动采集也要考虑对源系统的压力。

自动采集的架构通常分三层:

  1. 连接层:管理数据源连接信息(地址、端口、认证)
  2. 解析层:将源系统的元数据格式转为统一模型
  3. 写入层:将解析后的元数据写入存储层

下面这张图展示了自动采集的典型流程:

自动采集架构流程图 关系型数据库 Hadoop 生态 消息队列 连接层 JDBC / API / SDK 解析层 统一模型转换 写入层 存储 说明:连接层负责协议适配,解析层做格式转换,写入层持久化到元数据存储 增量采集通过对比时间戳或版本号实现,避免全量扫描

3.3 存储模型:选关系还是选图?

元数据采回来之后,放哪儿?这是个灵魂拷问。

市面上主流就两种存储模型:关系模型和图模型。我两种都用过,各有各的脾气。

3.3.1 关系模型:传统但稳定

关系模型就是把元数据存到关系型数据库里,比如 MySQL、PostgreSQL。表结构设计得像数据字典:一张表存表信息,一张表存字段信息,外键关联。

举个例子:

-- 表信息表
CREATE TABLE metadata_tables (
    table_id INT PRIMARY KEY,
    table_name VARCHAR(255),
    schema_name VARCHAR(255),
    db_name VARCHAR(255),
    created_at TIMESTAMP
);

-- 字段信息表
CREATE TABLE metadata_columns (
    column_id INT PRIMARY KEY,
    table_id INT REFERENCES metadata_tables(table_id),
    column_name VARCHAR(255),
    data_type VARCHAR(50),
    is_nullable BOOLEAN,
    description TEXT
);

-- 血缘关系表
CREATE TABLE metadata_lineage (
    lineage_id INT PRIMARY KEY,
    source_table_id INT,
    target_table_id INT,
    etl_job_name VARCHAR(255)
);

关系模型的优点:

  • 成熟稳定,事务支持好
  • 查询灵活,SQL 随手写
  • 权限控制精细

缺点也很明显:

  • 多对多关系(比如字段级血缘)查询性能差,要 JOIN 很多表
  • 模型扩展困难,加一种元数据类型就要加表
  • 层级结构(比如嵌套的 JSON Schema)表达不自然
注意:关系模型适合元数据类型固定、查询模式简单的场景。如果你要频繁做「从这张表追溯到上游十层」的血缘分析,关系模型会让你想骂人。

3.3.2 图模型:天生为关联而生

图模型用节点和边来表示元数据。节点是实体(表、字段、ETL 作业),边是关系(属于、派生自、依赖)。

我最早接触图模型是在一个金融项目里,要做全链路数据血缘。用关系模型查一条血缘链路要 JOIN 七八张表,响应时间 5 秒以上。换成 Neo4j 之后,同样的查询 200 毫秒搞定。

图模型的优势:

  • 关联查询极快,深度遍历性能好
  • 模型灵活,加节点加边不用改 schema
  • 直观,可视化天然匹配

劣势:

  • 事务能力弱于关系型数据库
  • 运维成本高,图数据库生态不如关系型成熟
  • 复杂聚合查询(比如 group by)不如 SQL 方便

3.4 怎么选?我的决策框架

你可能会问:那我到底用哪个?

我个人习惯用这个决策矩阵:

场景 推荐模型 理由
数据目录(表、字段清单) 关系模型 结构固定,查询简单
数据血缘(字段级溯源) 图模型 深度遍历性能碾压
业务术语管理 关系模型 层级浅,关联少
影响分析(改一个字段影响哪些下游) 图模型 反向遍历效率高
混合场景(目录+血缘+术语) 双模存储 关系存基础信息,图存关联
我的建议:别在一棵树上吊死。我在一个项目中用过「双模存储」——MySQL 存元数据基础信息,Neo4j 存血缘关系。查询时根据场景路由到不同的存储。虽然架构复杂了点,但效果很好。

3.5 存储模型对比总结

最后,用一张对比表收尾:

维度 关系模型 图模型
代表产品 MySQL, PostgreSQL Neo4j, JanusGraph
查询语言 SQL Cypher, Gremlin
关联查询性能 随深度指数下降 随深度线性增长
Schema 灵活性 低(需提前定义) 高(无模式)
事务支持 强(ACID) 弱(BASE)
运维复杂度 低 中高
可视化友好度 低 高