游乐游手机版
首页/AI教程/文章详情

自建数据质量检核引擎与开源方案选型踩坑实录

时间:2026-08-14 21:20
自建数据质量检核引擎 vs 开源方案,选型踩坑记录我们做数据治理平台的时候,数据质量检核是绕不开的模块。需求很明确:支持空值检查、唯一性校验、值域合规、跨表一致性、自定义 SQL 规则,支持定时调度和告警,能接入现有的数据治理平台。面对这个需求,两条路:自建,还是用开源方案。我们花了三周时间,对 A

自建数据质量检核引擎 vs 开源方案,选型踩坑记录

我们做数据治理平台的时候,数据质量检核是绕不开的模块。需求很明确:支持空值检查、唯一性校验、值域合规、跨表一致性、自定义 SQL 规则,支持定时调度和告警,能接入现有的数据治理平台。

自建数据质量检核引擎 vs 开源方案,选型踩坑记录

面对这个需求,两条路:自建,还是用开源方案。

我们花了三周时间,对 Apache Griffin、Amazon Deequ、Great Expectations 三个开源方案做了深度 POC,同时搭了一个自建原型做对比。最终的选择出乎意料——核心检核引擎自建,辅助能力用开源补位。

这篇文章记录整个选型过程和踩过的坑,希望能帮到面临同样抉择的团队。


一、候选方案速览

1.1 Apache Griffin

Apache 基金会旗下的数据质量方案,2016 年进入孵化器,2018 年毕业。架构上分三块:Measure(检核规则定义)、Job(调度执行)、Service(结果展示)。

技术栈:Spark Livy Elasticsearch MySQL。检核逻辑在 Spark 上执行,通过 Livy 提交 Spark Job,结果写入 ES 和 MySQL。

1.2 Amazon Deequ

AWS 开源的数据质量库,基于 Spark 实现。核心是 Analyzer(指标计算)和 VerificationSuite(规则校验),纯库形式,不提供调度、UI、告警等平台能力。

1.3 Great Expectations

Python 生态最流行的数据质量框架,核心理念是"Expectation"——声明式定义数据应该长什么样。支持 Pandas、Spark、SQL 三种后端,文档和社区活跃度极高。

1.4 自建方案

基于 Spark SQL 规则引擎的思路,规则配置存 MySQL,Spark 任务定时执行,结果写回 MySQL,前端展示和告警用现有平台能力。


二、POC 对比

我们用同一份测试数据(5000 万行订单表,32 个字段,Hive 格式,Snappy 压缩),配置了 15 条典型质量规则,在三套方案上跑了一轮完整的 POC。

2.1 部署复杂度

方案部署组件首次可运行耗时GriffinSpark Livy ES MySQL ZK2 天DeequSpark(纯库依赖)30 分钟Great ExpectationsPython Spark/Pandas1 小时自建Spark MySQL4 小时

Griffin 的部署是最痛苦的。它依赖 Livy 来提交 Spark 任务,但 Livy 本身是一个半死不活的项目(Apache 孵化器,社区活跃度极低),版本兼容性令人抓狂。我们试了 Griffin 0.7 Livy 0.7,报错;降到 Griffin 0.6 Livy 0.6,还是报错;最后在 GitHub Issue 里翻到某个老哥的 Hack 方案,手动改了 Griffin 源码里的 Livy 客户端版本才跑通。

结论:Griffin 的部署成本远超预期,不建议在生产环境直接使用。

2.2 检核性能

5000 万行数据,15 条规则:

从执行结果看,几种方案在时间和资源占用上的差异还是比较直观的:Griffin 用时 4 分 12 秒,资源配置为 8 executors × 4g;Deequ 用时 2 分 48 秒,同样是 8 executors × 4g;Great Expectations(Spark)耗时 3 分 35 秒,配置依旧是 8 executors × 4g;自建方案最快,为 2 分 15 秒,资源占用也是 8 executors × 4g。

Deequ 和自建方案最快,两者的检核逻辑都是直接在 Spark DataFrame 上做聚合操作,没有额外的序列化和中间存储开销。Griffin 最慢,因为它需要经过 Livy 的 REST 接口提交任务,中间多了一层序列化/反序列化,而且它的 Measure 抽象层引入了额外的计算开销。

2.3 规则表达能力

能力GriffinDeequGreat Expectations自建空值检查✓✓✓✓唯一性✓✓✓✓值域/枚举✓✓✓✓正则匹配✓✗✓✓跨表一致性✓✗✗✓自定义 SQL✓✗✓✓时间窗口✓✓✗✓增量检核✗✓✗✓

Deequ 最大的短板是不支持跨表一致性检查。比如"订单表的客户 ID 必须在客户主数据表中存在"这种引用完整性校验,Deequ 做不了。这在生产环境是刚需。

Great Expectations 的跨表一致性也不支持,它的设计哲学是"一次只检查一个数据集"。

Griffin 的规则定义能力最全,但配置方式非常繁琐——需要通过 JSON 文件定义 Measure,格式复杂,可读性差。

2.4 平台集成能力

能力GriffinDeequGreat Expectations自建原生 UI✓✗✗可定制调度能力✓✗✗可定制告警通知有限✗✗可定制REST API✓✗✗可定制数据治理平台集成困难灵活灵活无缝

Griffin 有 UI 但不好用。 它的 UI 是 Angular 1.x 写的,2019 年后就没更新过,界面风格和交互体验停留在 5 年前。而且它的前端和后端耦合很紧,想把检核结果嵌入到我们自己的数据治理平台,需要改 Griffin 源码。

Deequ 和 Great Expectations 没有 UI。 它们都是库,不是平台。检核结果需要你自己消费、自己展示、自己告警。如果你已经有数据治理平台,这反而是优势——更灵活。


三、各自的坑

3.1 Griffin 的坑

Livy 依赖是最大痛点。 前面说了部署问题,但更麻烦的是运行时稳定性。Livy 的 Session 管理有严重的内存泄漏问题,长时间运行后 Session 会 OOM,导致 Spark Job 提交失败。我们 POC 期间跑了 3 天,Livy 挂了 2 次。

JSON 规则定义可维护性差。 一条"检查 customer_id 不为空"的规则,Griffin 的 JSON 配置超过 30 行:

代码语言:ja vascript

复制

{"name": "accu_check","type": "accuracy","process.type": "batch","data.sources": [{"name": "source","connector": {"name": "hive","version": "1.2","config": {"database": "ods","table.name": "orders"}}}],"evaluate.rule": {"rules": [{"dsl.type": "griffin-dsl","dq.type": "accuracy","rule": "customer_id IS NOT NULL","details": {"source": "source","target": "target"}}]}}

30 行 JSON 表达一条"不为空"规则,业务方根本没法自助配置。每次新增规则都要数仓开发来写 JSON,效率极低。

社区活跃度低。 Griffin 的 GitHub 最后一次 Release 是 2021 年的 0.7.0。2022 年至今只有 3 个 commit,基本上处于维护停滞状态。对于一个需要长期维护的基础组件,这个风险不可接受。

3.2 Deequ 的坑

Analyzer 和 VerificationSuite 是两个模型,关联逻辑复杂。 Deequ 的 Analyzer 负责计算指标(如完整性、唯一性、均值),VerificationSuite 负责检查规则。但如果你想把 Analyzer 的结果作为 VerificationSuite 的输入(比如"检查完整性是否低于上个月"),需要手动拼接两个 API,代码体验很差。

不支持自定义 SQL 规则。 Deequ 的规则定义基于它的 DSL,无法直接嵌入 SQL。如果你的质量规则是"订单金额 > 0 且订单金额 < 100000",没问题。但如果规则是"执行这段 SQL,结果集为空则通过",做不到。

Scala 优先,Ja va/Python API 不完整。 Deequ 的核心 API 是 Scala 的,虽然提供了 Python 封装(PyDeequ),但很多高级功能(如 Anomaly Detection、增量检核)在 Python 版中不可用。

3.3 Great Expectations 的坑

Expectation Suite 的 JSON 文件膨胀。 一个包含 50 条规则的 Suite,JSON 文件超过 5000 行。虽然 GE 提供了 CLI 和 Jupyter Notebook 交互式创建 Expectation 的方式,但在生产环境中,规则的管理和维护仍然是个问题——版本控制、规则复用、批量修改,都不方便。

Python 生态,与 Ja va/Spark 主栈的集成有摩擦。 我们的数据平台是 Ja va 技术栈,GE 是纯 Python 项目。虽然可以通过 Airflow 调度 GE 的 Python 脚本,但在日志、监控、告警等环节的集成成本比纯 Ja va 方案高。

Data Docs 好看但不够实用。 GE 的 Data Docs 是它的特色功能——自动生成漂亮的数据质量报告。但静态 HTML 报告在企业场景下不够用,你需要的是一个 API,让前端按需查询检核结果,而不是打开一个 HTML 文件。


四、最终方案:自建核心 开源补位

综合 POC 结果和团队情况,我们最终选择了自建核心检核引擎,部分能力用开源方案补位。

4.1 核心检核引擎:自建

架构很简单:

代码语言:ja vascript

复制

定时调度(Azkaban/DolphinScheduler)→ 拉取规则配置(MySQL)→ 生成 Spark SQL→ 提交 Spark Job→ 结果写回 MySQL→ 前端展示 告警

规则配置表设计:

代码语言:ja vascript

复制

CREATE TABLE dq_rule (idBIGINT PRIMARY KEY AUTO_INCREMENT,rule_name VARCHAR(200)NOT NULL COMMENT '规则名称',rule_type VARCHAR(50) NOT NULL COMMENT '规则类型:NOT_NULL/UNIQUE/RANGE/REGEX/CROSS_TABLE/CUSTOM_SQL',target_db VARCHAR(100)COMMENT '目标库',target_table VARCHAR(100) NOT NULL COMMENT '目标表',target_colVARCHAR(100)COMMENT '目标字段',rule_config TEXTNOT NULL COMMENT '规则配置JSON',expect_result VARCHAR(50) COMMENT '期望结果:PASS/FAIL',schedule_cron VARCHAR(50)COMMENT '调度表达式',enabled TINYINT DEFAULT 1,create_time DATETIMEDEFAULT CURRENT_TIMESTAMP);

规则配置 JSON 示例:

代码语言:ja vascript

复制

{"type": "NOT_NULL","threshold": 0.99,"comment": "customer_id 完整率不低于 99%"}代码语言:ja vascript

复制

{"type": "CROSS_TABLE","source_table": "ods.orders","source_col": "customer_id","target_table": "dim.customer","target_col": "id","join_type": "LEFT_ANTI","comment": "订单表的客户ID必须在客户主数据表存在"}代码语言:ja vascript

复制

{"type": "CUSTOM_SQL","sql": "SELECT COUNT(*) FROM ods.orders WHERE order_amount <= 0 OR order_amount > 100000","expect": "ZERO","comment": "订单金额不得为负数或超过10万"}

Spark 执行逻辑(核心代码):

代码语言:ja vascript

复制

def executeRule(rule: DqRule, spark: SparkSession): DqResult = {rule.ruleType match {case "NOT_NULL" =>val config = parseConfig(rule.ruleConfig)val totalCount = spark.sql(s"SELECT COUNT(*) FROM ${rule.targetTable}").collect()(0).getLong(0)val nullCount = spark.sql(s"SELECT COUNT(*) FROM ${rule.targetTable} WHERE ${rule.targetCol} IS NULL").collect()(0).getLong(0)val ratio = 1.0 - nullCount.toDouble / totalCountDqResult(rule.id, rule.ruleName, ratio >= config.threshold, ratio, s"完整率: ${ratio * 100}%")case "CROSS_TABLE" =>val config = parseConfig(rule.ruleConfig)val violateCount = spark.sql(s"""SELECT COUNT(*) FROM ${config.sourceTable} s |LEFT ANTI JOIN ${config.targetTable} t |ON s.${config.sourceCol} = t.${config.targetCol}""".stripMargin).collect()(0).getLong(0)DqResult(rule.id, rule.ruleName, violateCount == 0, violateCount,s"引用完整性违规: ${violateCount} 条")case "CUSTOM_SQL" =>val config = parseConfig(rule.ruleConfig)val result = spark.sql(config.sql).collect()(0).getLong(0)val pass = config.expect == "ZERO" && result == 0DqResult(rule.id, rule.ruleName, pass, result, s"自定义SQL结果: ${result}")}}

4.2 用开源补位:Deequ 做指标分析

自建规则引擎覆盖了 80% 的日常检核场景,但有一个能力我们没做——数据画像和异常检测。

Deequ 的 Analyzer 和 Anomaly Detection 在这块做得很好。我们把它作为辅助模块集成进来:每周跑一次完整的数据画像(完整性、唯一性、均值、标准差、直方图),用 Deequ 的 AnomalyDetectionStrategy 检测指标异常。

代码语言:ja vascript

复制

import com.amazon.deequ.analyzers._import com.amazon.deequ.anomalydetection.{AnomalyDetectionStrategy, RelativeRateOfChangeStrategy}val analyzers = Seq(Completeness("customer_id"),Uniqueness("order_id"),Mean("order_amount"),StandardDeviation("order_amount"))val analysisResult = AnalysisRunner.onData(df).addAnalyzers(analyzers).useRepository(metricsRepository)// 把历史指标一并纳入,用来做异常检测.run()

4.3 成本对比

如果把项目自建和开源方案放在一起看,差异其实很直接:首次开发分别是3 人月和1 人月;持续维护分别是0.5 人月/年和1 人月/年,后者这部分主要花在修兼容问题、跟进社区变化上。再往下看,定制化成本是低和高的区别;平台集成方面,一个是原生支持,另一个通常还得做二次开发;至于长期风险,一边更依赖团队本身,另一边则更看社区活跃度。

自建的前期投入更高,但长期维护成本更低,定制化效率远超开源方案。


五、选型决策框架

如果你的团队面临同样的抉择,我建议按以下决策树判断:

代码语言:ja vascript

复制

是否需要 UI 和调度能力?├─ 需要 → 团队有 Ja va 技术栈? → 自建├─ 需要 → 团队是 Python 栈? → Great Expectations Airflow└─ 不需要 → 继续是否需要跨表一致性检查?├─ 需要 → 自建 或 Griffin(如果接受部署复杂度)└─ 不需要 → 继续核心检核逻辑是否能用 SQL 表达?├─ 能 → 自建(成本最低,效果最好)└─ 不能 → Deequ(复杂统计分析场景)是否需要长期维护和社区支持?├─ 需要 → 自建 或 Great Expectations└─ 不需要 → Griffin(如果团队能接受停更风险)


六、最后说一句

数据质量检核引擎在技术上没有银弹——开源方案看起来"拿来就用",但真正接入生产环境后,你会发现大量的时间花在修兼容问题、补缺失功能、改 UI 集成上。这些时间加起来,往往不比自建少。

自建不意味着从零开始。 用 Deequ 做指标分析,用 Great Expectations 做数据文档,用 Spark SQL 做规则检核——把开源方案当作"库"而不是"平台",各取所长,组装成适合自己的方案。

技术选型的最高境界,不是选最好的方案,是选最适合你团队能力和业务场景的方案。


本文基于作者团队在数据治理平台建设中的真实选型经验。性能数据来自 5000 万行测试数据集,实际生产环境数据量级不同,结论可能不同,请以自身 POC 结果为准。

来源:https://cloud.tencent.com.cn/developer/article/2722273
上一篇用WorkBuddy搭建A股投研流水线:信息整合与决策留痕 下一篇腾讯乐享企业AI知识库建设:为什么第一步是连接
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
CAD零基础入门教程:坐标输入、图层管理与基础绘图命令
AI教程 · 2026-09-01

CAD零基础入门教程:坐标输入、图层管理与基础绘图命令

本文面向CAD零基础学习者,系统讲解坐标输入、图层管理与基础绘图命令的核心用法。通过分步实操与常见问题排查,帮助新手建立精确绘图习惯,掌握规范出图的基础能力。

CAD从入门到项目交付:绘图、标注、图块与实战工作流
AI教程 · 2026-09-01

CAD从入门到项目交付:绘图、标注、图块与实战工作流

掌握CAD的核心在于建立“画得准、标得清、复用快、交付稳”的工作流。本文提供从环境设置、高频命令组合、标注规范、图块标准化到项目分阶段交付的完整路径,帮助初学者避免常见返工陷阱,独立完成可检查、可复用、可打印的工程图纸。

Claude Code 登录指南:个人、Teams 与企业账号区分与授权步骤
AI教程 · 2026-09-01

Claude Code 登录指南:个人、Teams 与企业账号区分与授权步骤

本文详细解析 Claude Code 登录前的账号类型区分方法,涵盖个人订阅、Teams 席位与企业 Enterprise 席位的授权路径差异。提供终端登录命令、环境变量排查及常见异常处理步骤,帮助用户快速完成正确授权并避免登录路径混淆。

Claude Code 文件修改前的权限模式配置与命令审批指南
AI教程 · 2026-09-01

Claude Code 文件修改前的权限模式配置与命令审批指南

本文详细介绍Claude Code在修改文件前的权限模式配置方法,包括defaultMode可选值、permissions allow与deny规则设置、多层级配置文件管理以及 status验证技巧,帮助开发者安全高效地使用AI编程助手。

Claude Code接入VS Code后先测扩展和终端命令
AI教程 · 2026-09-01

Claude Code接入VS Code后先测扩展和终端命令

在VS Code中接入Claude Code后,建议优先验证扩展面板与集成终端两条入口。本文提供标准检查顺序、关键命令与常见故障排查路径,帮助你快速确认环境就绪,避免后续开发受阻。