数据源接入与探查:先摸清家底,再谈治理

数据质量工程的第一步,不是写规则,也不是搭平台。而是——你得先知道你的数据长什么样、从哪来、能信几分。

我见过太多团队,一上来就搞数据质量规则,结果发现源系统字段类型都变了,或者某些表根本没人维护。说白了,数据源接入和探查,就是给数据做一次「入职体检」。这一步做扎实了,后面的治理工作才能站得住脚。

数据源类型识别:你的数据是哪种「物种」?

数据源不是铁板一块。我个人习惯,先把数据源分成三大类:

类型 典型代表 接入特点 质量风险
结构化 MySQL、PostgreSQL、Oracle、SQL Server Schema 固定,JDBC/ODBC 直连 字段类型变更、空值率波动
半结构化 JSON 日志、XML、CSV、Parquet Schema on read,需解析器 字段缺失、嵌套层级不一致
非结构化 图片、PDF、音视频、文本 对象存储或消息队列 元数据缺失、内容无法直接校验

你想想看,一个 JSON 日志文件,今天多了一个字段,明天少了一个层级,如果你用固定 Schema 去解析,直接就崩了。所以识别数据源类型,决定了你用什么工具、什么策略去探查。

我的经验: 别只看数据库类型。同一个 MySQL 实例里,有的表是业务核心表,有的是临时缓存表。我建议先做一次「数据源分类清单」,按业务域、更新频率、数据量级打标签。这样后面探查时,优先级就清楚了。

数据探查工具:Great Expectations 实战

说到数据探查工具,Great Expectations(简称 GX)是我目前用得最顺手的。为什么?因为它把「探查」和「断言」合在了一起。你探查出来的结果,直接就能转成质量规则。

我记得第一次在项目里用 GX,团队里还有人质疑:「这不就是个测试框架吗?」嗯,还真不是。GX 的核心是 Expectation——你对数据的一个预期。比如:

  • expect_column_values_to_not_be_null("user_id") —— user_id 不能为空
  • expect_column_values_to_be_between("age", 0, 150) —— 年龄在合理范围
  • expect_table_row_count_to_be_between(1000, 100000) —— 行数不能太少或太多

下面是一个典型的 GX 探查流程:

# 1. 安装
pip install great_expectations

# 2. 初始化数据上下文
import great_expectations as gx
context = gx.get_context()

# 3. 连接数据源
datasource = context.sources.add_pandas("my_datasource")
data_asset = datasource.add_dataframe_asset("my_asset")
batch_request = data_asset.build_batch_request(dataframe=df)

# 4. 创建 Expectation Suite
suite = context.add_expectation_suite("user_profile_suite")

# 5. 添加探查期望
suite.add_expectation(
    gx.expectations.ExpectColumnValuesToNotBeNull(column="user_id")
)
suite.add_expectation(
    gx.expectations.ExpectColumnValuesToBeBetween(column="age", min_value=0, max_value=150)
)

# 6. 运行验证
validator = context.get_validator(
    batch_request=batch_request,
    expectation_suite=suite
)
results = validator.validate()
print(results["statistics"])

跑完之后,GX 会生成一个 HTML 报告,哪些字段通过了、哪些失败了、失败率多少,一目了然。我曾经在一个电商项目里,用 GX 跑了一遍订单表,发现「支付金额」字段有 3% 的记录是负数——业务方自己都不知道。这就是探查的价值。

核心要点: 探查不是一次性工作。我建议把 GX 的 Expectation Suite 纳入 CI/CD 流水线,每次数据接入都自动跑一遍。这样数据质量的变化,你第一时间就能感知到。

元数据采集:给数据做「身份证」

元数据是什么?说白了,就是「关于数据的数据」。字段名、类型、长度、注释、主键、外键、血缘关系……这些都是元数据。

没有元数据,你连这个字段是干嘛的都不知道,谈何质量治理?

我常用的元数据采集方式有三种:

  1. JDBC 元数据接口:通过 DatabaseMetaData 获取表结构、主键、索引。适合关系型数据库。
  2. 文件头解析:Parquet 的 schema、CSV 的第一行、JSON 的 key 集合。适合半结构化数据。
  3. 日志/API 采集:从数据源的管理接口或审计日志中获取变更记录。适合实时监控。

举个例子,用 Python 采集 MySQL 元数据:

import pymysql

conn = pymysql.connect(host="localhost", user="root", password="pass", database="test")
cursor = conn.cursor()

# 获取所有表
cursor.execute("SHOW TABLES")
tables = cursor.fetchall()

for table in tables:
    table_name = table[0]
    # 获取表注释
    cursor.execute(f"SHOW TABLE STATUS WHERE Name = '{table_name}'")
    status = cursor.fetchone()
    comment = status[17]  # 第18列是注释
    print(f"表: {table_name}, 注释: {comment}")

    # 获取字段信息
    cursor.execute(f"SHOW FULL COLUMNS FROM {table_name}")
    columns = cursor.fetchall()
    for col in columns:
        print(f"  字段: {col[0]}, 类型: {col[1]}, 注释: {col[8]}")
避坑指南: 我曾经在一个项目里,直接在生产库上跑全量元数据采集,结果把数据库连接池打满了,导致业务短暂中断。后来我改成「增量采集 + 限流」策略——每天凌晨采集一次,每次只采集变更的表。记住,元数据采集也要考虑对源系统的影响。

知识体系总览

下面这张图,把数据源接入与探查的核心逻辑串起来了。你可以把它当作本章的「思维导图」:

数据源接入与探查知识体系 数据源接入与探查 数据源类型识别 结构化 半结构化 非结构化 数据探查工具 (GX) Expectation Validation 报告生成 元数据采集 JDBC接口 文件头解析 日志/API 输出:数据质量基线 + 元数据目录 💡 说明: 数据源类型识别决定了探查策略,探查工具(GX)生成质量基线,元数据采集构建数据目录。 三者缺一不可。我建议按「先分类 → 再探查 → 后采集」的顺序推进, 每一步的输出都作为下一步的输入,形成闭环。

接入与探查的常见陷阱

做了这么多年数据治理,我踩过不少坑。挑几个典型的说说:

  • 陷阱一:只探查一次。数据源是会变的。字段类型从 int 变成 varchar,你第一次探查没问题,三个月后可能就全崩了。我建议至少每周跑一次全量探查,每天跑一次增量探查。
  • 陷阱二:忽略空值率。很多团队只看字段有没有值,不看空值率的变化。比如「手机号」字段,昨天空值率 2%,今天突然变成 20%——这往往是上游接口出了问题。
  • 陷阱三:元数据采集太「重」。我曾经见过一个团队,用 Apache Atlas 做全量元数据采集,部署了 10 台服务器,结果每天采集的数据量还没元数据本身大。小团队的话,用 GX 自带的元数据功能,或者写个轻量脚本就够了。
我的建议: 刚开始做数据探查,别追求大而全。选 3-5 个核心表,用 GX 跑一遍 Expectation,把元数据采回来。先跑通一个闭环,再逐步扩展。数据治理是马拉松,不是百米冲刺。