3、数据血缘的采集技术:解析SQL、解析ETL脚本、通过日志采集、通过API采集

数据血缘采集,说白了就是搞清楚数据从哪来、到哪去、中间经历了什么。很多团队一上来就搞血缘,结果发现采集不全、不准、不及时。嗯,这里面的坑,我踩过不少。

我个人习惯把采集技术分成四类:SQL解析、ETL脚本解析、日志采集、API采集。它们各有各的适用场景,也各有各的脾气。下面我一个个说。

3.1 解析SQL:最直接的血缘来源

SQL是数据加工最常用的语言。无论是简单的SELECT,还是复杂的嵌套子查询,SQL里天然就带着输入表和输出表的关系。解析SQL,就是把这些关系提取出来。

我建议你优先做SQL解析,因为它准确率高、成本低。但要注意,不是所有SQL都好解析。

我的经验: 解析SQL时,优先处理INSERT ... SELECT和CREATE TABLE ... AS SELECT这两种模式。它们直接表达了“数据从哪张表来,写到哪张表去”。我早期做的一个项目,光靠解析这两种SQL,就覆盖了70%的血缘关系。

解析SQL的常见步骤:

  1. 词法分析:把SQL拆成,识别关键字、表名、字段名。
  2. 语法分析:构建抽象语法树(AST),理解SQL的逻辑结构。
  3. 血缘提取:从AST中找出FROM、JOIN、子查询中的输入表,以及INSERT、CREATE中的输出表。
  4. 字段级映射:分析SELECT列表中的字段表达式,建立输入字段到输出字段的映射关系。

举个例子,下面这条SQL:

INSERT INTO dws.daily_sales
SELECT
    o.order_id,
    o.order_date,
    oi.product_id,
    oi.quantity * oi.unit_price AS amount
FROM
    ods.orders o
    JOIN ods.order_items oi ON o.order_id = oi.order_id
WHERE
    o.order_date = '2024-01-01';

解析后,我们能得到:

  • 输入表:ods.orders、ods.order_items
  • 输出表:dws.daily_sales
  • 字段映射:o.order_id → order_id,o.order_date → order_date,oi.product_id → product_id,oi.quantity * oi.unit_price → amount
避坑指南: 我曾经遇到过一个坑——动态SQL。有些系统会在代码里拼接SQL,比如用字符串变量拼表名、字段名。这种SQL在运行时才能确定具体内容,静态解析根本拿不到。我的建议是:先做静态解析覆盖大部分场景,再配合日志采集兜底。

3.2 解析ETL脚本:搞定复杂加工逻辑

很多企业的数据加工不是纯SQL,而是用ETL工具(比如Informatica、DataStage、Kettle)或者脚本语言(Python、Shell)来实现。这时候,解析SQL就不够用了。

解析ETL脚本,核心是理解脚本里的数据流逻辑。比如一个Python脚本,可能先读CSV文件,然后做数据清洗,最后写入数据库。我们需要从代码里识别出这些数据源和目标。

我常用的方法:

  • 正则匹配:对于简单的脚本,用正则匹配出文件路径、数据库连接串、表名。
  • 抽象语法树(AST):对于Python、Java等语言,解析AST能更准确地提取数据流。
  • 工具元数据:很多ETL工具(如Informatica)会生成XML或JSON格式的元数据文件,直接解析这些文件比解析脚本本身更靠谱。
ETL工具/语言 推荐解析方式 注意事项
Informatica 解析XML元数据文件 注意版本差异,不同版本XML结构可能不同
Kettle (PDI) 解析.ktr/.kjb文件 文件是XML格式,但节点命名不统一
Python脚本 AST解析 + 正则 注意pandas.read_csv、sqlalchemy等常见库的调用模式
Shell脚本 正则匹配 重点关注hive -e、mysql -e等命令
关键点: 解析ETL脚本时,不要试图覆盖所有语法。先识别出最常见的几种数据读写模式,覆盖80%的场景。剩下的20%,可以用人工标注或日志采集来补充。

3.3 通过日志采集:无侵入的兜底方案

有些系统,你拿不到SQL,也看不懂ETL脚本。比如商业软件、老旧系统、或者外包团队写的“黑盒”代码。这时候,日志采集就是你的救命稻草。

日志采集的原理很简单:监听数据系统的操作日志,从中提取血缘信息。比如数据库的审计日志、Hive的作业日志、Spark的Driver日志,里面都记录了谁、在什么时候、对哪些表做了什么操作。

我建议你重点关注以下几种日志:

  • 数据库审计日志:记录所有SQL执行情况,包括INSERT、UPDATE、DELETE、SELECT。
  • Hive/Spark作业日志:记录作业的输入输出表、执行计划。
  • 调度系统日志:记录任务依赖关系,间接反映数据流向。
  • 应用日志:业务系统打印的数据操作记录。

日志采集的流程:

  1. 日志收集:用Flume、Filebeat、Logstash等工具把日志集中起来。
  2. 日志解析:根据日志格式,提取关键字段(时间、操作类型、表名、字段名)。
  3. 血缘构建:把解析出的信息组装成血缘关系。
  4. 去重与合并:同一操作可能被多次记录,需要去重。
避坑指南: 我曾经在一个项目里,日志采集做得太“全”,结果把SELECT查询也当成了血缘关系。你想想看,用户随便查个报表,日志里就多了一条血缘,这显然不对。我的建议是:只关注写操作(INSERT、UPDATE、DELETE)和创建表的操作,读操作一般不做血缘。

3.4 通过API采集:对接标准化平台

现在很多数据平台(如DataWorks、Databricks、Snowflake)都提供了元数据API。通过API采集,是最省力的方式——不用自己解析,平台已经把血缘关系算好了,你直接调接口拿就行。

API采集的优点是:

  • 准确:平台自己生成的元数据,比外部解析更可靠。
  • 实时:API通常能拿到最新的血缘信息。
  • 全面:除了表级血缘,还能拿到字段级、作业级血缘。

但缺点也很明显:

  • 依赖平台:如果平台不支持,或者API不开放,就没法用。
  • 格式不统一:不同平台的API返回格式千差万别,需要做适配。
  • 权限限制:有些API需要管理员权限才能调用。

我常用的做法是:把API采集作为“主数据源”,SQL解析和日志采集作为“补充”。比如在DataWorks上,我直接调它的OpenAPI拿血缘;对于自建Hadoop集群,我就用SQL解析+日志采集。

我的经验: 对接API时,先看平台有没有提供变更事件推送功能。如果有,优先用事件推送,而不是轮询。轮询太频繁会浪费资源,太稀疏又可能漏掉变更。我曾经用轮询方式每5分钟调一次API,结果平台那边限流了,搞得两边都很尴尬。

3.5 四种采集技术的对比与选型

说了这么多,到底该用哪种?我整理了一张对比表,方便你决策:

采集技术 适用场景 准确率 实施成本 维护成本
SQL解析 纯SQL加工、数据仓库 高 中 低
ETL脚本解析 复杂ETL流程、脚本加工 中 高 高
日志采集 黑盒系统、老旧系统 中 低 中
API采集 标准化数据平台 高 低 低

我的建议是:能调API就调API,调不了就解析SQL,SQL解析不了再考虑日志采集。ETL脚本解析,除非你团队有足够的人力维护,否则尽量少碰。

核心原则: 血缘采集不是一次性的工作,而是持续迭代的过程。先跑通一个最小闭环,再逐步覆盖更多场景。不要追求100%覆盖,80%的血缘准确率,就能支撑大部分数据治理工作了。

3.6 本章知识体系

下面这张图,帮你梳理了四种采集技术的核心逻辑和关系:

数据血缘采集技术体系 血缘采集引擎 SQL解析 ETL脚本解析 日志采集 API采集 词法分析 → 语法分析 AST → 血缘提取 字段级映射 正则匹配 / AST 工具元数据解析 数据流逻辑提取 审计日志 / 作业日志 日志收集 → 解析 血缘构建 → 去重 平台OpenAPI调用 事件推送 / 轮询 元数据标准化适配 选型优先级:API > SQL解析 > 日志采集 > ETL脚本解析 目标:覆盖80%场景,持续迭代,不追求100%