元数据采集:手动采集 vs 自动采集

元数据采集,说白了就是把你数据库里那些「关于数据的数据」给捞出来。我刚开始做数据治理那会儿,觉得这事特简单——不就是查几个系统表嘛。后来才发现,采集方式选不对,后面整个数据目录都是坑。

今天咱们就聊聊采集的两种主流方式:手动和自动。以及两个最常用的技术手段:JDBC/ODBC 和 API。

手动采集 vs 自动采集

先看个对比,心里有个底:

对比维度 手动采集 自动采集
操作方式 人工编写 SQL / 导出 CSV 调度任务定时执行
实时性 低,依赖人工触发 高,可配置分钟级
准确性 容易出错,漏字段是常事 稳定,按规则执行
适用场景 临时调研、小规模验证 生产环境、大规模治理
维护成本 低(但隐性成本高) 初期高,后期省心

手动采集,我最早在项目里用过。那时候团队刚起步,就几张表,我直接连上数据库跑 SELECT * FROM information_schema.columns,然后把结果贴到 Excel 里。嗯,当时觉得挺快。但后来表多了,业务方天天改字段,我每周都要手动跑一遍,漏一次就出问题。

避坑指南: 我曾经在一个中型项目中,因为手动采集漏掉了某个核心表的字段变更,导致下游报表跑出来全是错的。那周我加了三天班。所以,只要超过 10 张表,就别用手动了。

自动采集就不一样了。你写一个采集脚本,挂到调度平台上,每天凌晨跑一次。新表、新字段自动入库,你只需要看增量报告就行。说白了,自动采集才是数据目录的「心脏」。

JDBC/ODBC 采集数据库元数据

JDBC 和 ODBC 是两种最经典的数据库连接协议。JDBC 是 Java 生态的,ODBC 是微软家的。但不管哪种,核心思路都一样:通过标准接口,读取数据库的系统表或视图。

我习惯用 JDBC,因为 Java 生态的工具链太成熟了。比如你要采集 MySQL 的元数据,核心代码就这几行:

// 获取数据库元数据
DatabaseMetaData metaData = connection.getMetaData();

// 获取所有表
ResultSet tables = metaData.getTables(null, null, "%", new String[]{"TABLE"});
while (tables.next()) {
    String tableName = tables.getString("TABLE_NAME");
    String tableComment = tables.getString("REMARKS");
    System.out.println("表名: " + tableName + ", 注释: " + tableComment);
}

// 获取指定表的列信息
ResultSet columns = metaData.getColumns(null, null, "user_info", "%");
while (columns.next()) {
    String colName = columns.getString("COLUMN_NAME");
    String colType = columns.getString("TYPE_NAME");
    int colSize = columns.getInt("COLUMN_SIZE");
    String colComment = columns.getString("REMARKS");
    System.out.println("字段: " + colName + ", 类型: " + colType + ", 大小: " + colSize + ", 注释: " + colComment);
}

你看,核心就两个方法:getTables() 和 getColumns()。但实际项目中,你还要处理更多信息:

  • 主键信息:getPrimaryKeys()
  • 索引信息:getIndexInfo()
  • 外键关系:getImportedKeys()
  • 存储过程:getProcedures()

我记得有一次,客户要求把 Oracle 里几百个存储过程的入参和出参都采集出来。我一开始用 getProcedureColumns() 一个个查,慢得要死。后来改成批量查询 ALL_ARGUMENTS 视图,效率直接翻了 10 倍。所以,JDBC 标准接口虽然好用,但遇到性能瓶颈时,别忘了直接查数据库原生的系统表。

小技巧: 不同数据库的 JDBC 驱动实现细节不一样。比如 MySQL 的 getTables() 默认不返回视图,需要把类型参数改成 new String[]{"VIEW"}。踩过一次坑之后,我每次都会先打印一下驱动版本。

API 采集

API 采集,说白了就是调用数据源对外暴露的 HTTP 接口来拿元数据。这招在云数据库、SaaS 平台、或者自研系统中特别常用。

举个例子,你要采集 AWS Glue 数据目录里的元数据,直接调它的 REST API:

GET /v1/databases/{databaseName}/tables HTTP/1.1
Authorization: Bearer <your->
Content-Type: application/json

响应示例:
{
  "TableList": [
    {
      "Name": "user_info",
      "CreateTime": "2024-01-15T10:30:00Z",
      "StorageDescriptor": {
        "Columns": [
          {"Name": "user_id", "Type": "int", "Comment": "用户ID"},
          {"Name": "user_name", "Type": "string", "Comment": "用户名"}
        ]
      }
    }
  ]
}

API 采集的好处很明显:

  • 跨平台:不管底层是 MySQL 还是 PostgreSQL,API 返回的 JSON 结构是统一的
  • 权限控制:API 本身就有认证和授权,不用暴露数据库密码
  • 增量采集:很多 API 支持按时间戳过滤,只拉取变更的部分

但 API 采集也有坑。我遇到过最头疼的问题就是限流。有一次对接某个云厂商的元数据 API,每分钟只能调 100 次。我那个数据目录里有 5000 多张表,按这个速度得跑将近一个小时。后来我加了本地缓存和重试机制,才勉强跑通。

核心原则: 能走 API 就别走 JDBC。API 是面向业务的接口,JDBC 是面向数据库的协议。在微服务架构下,API 采集更安全、更解耦。

三种采集方式的选型建议

你可能会问:那我到底该用哪种?我个人的经验是:

  1. 内部数据库(MySQL、PostgreSQL、Oracle):优先 JDBC,性能好,信息全
  2. 云数据库(AWS RDS、阿里云 RDS):优先 API,避免直连数据库
  3. SaaS 平台(Salesforce、Snowflake):只能用 API,没得选
  4. 自研系统:如果系统有元数据管理模块,优先 API;没有的话,退而求其次用 JDBC

下面这张图,是我在项目中总结的采集流程,你可以参考:

元数据采集流程框架 数据源层 采集方式层 采集技术层 元数据存储层 MySQL / PostgreSQL Oracle / SQL Server 手动采集 自动采集(调度) JDBC / ODBC REST API 元数据仓库 数据目录 选型建议 • 内部数据库 → JDBC • 云数据库 → API • SaaS 平台 → API • 自研系统 → API 优先 • 小规模验证 → 手动 • 生产环境 → 自动 • 性能优先 → JDBC • 安全优先 → API • 混合场景 → 两者结合

最后说一句,不管选哪种方式,元数据采集的最终目标不是「采到」,而是「采对」。我见过太多项目,采集脚本跑得飞起,但采回来的字段注释全是空的,或者类型映射错了。所以,每次上线前,一定要做一次人工抽检,看看采集结果和实际数据库是否一致。