规模化自动数据质量和监控指南-全-
规模化自动数据质量和监控指南(全)
原文:
zh.annas-archive.org/md5/aaae0dd90e52a04469741d36ba3c4f7b译者:飞龙
序言
问你一个快速的问题:如何辨别一个真正在生产环境中构建东西的数据科学家和一个只是玩弄数据的人?答案是:他们被数据质量彻底搞崩了。任何真正部署数据的人不仅有一个伤疤,而是从这个问题上遭受了整个身体的鞭打。
下面是数据科学团队的典型一天生活。一位高级执行官早上在仪表板上看到一些奇怪的东西,问这个数字是否正确,然后数据团队为了找出答案而奔波了接下来的 4 个小时。最终他们找到了忘记添加正确追踪机制的工程师。但现在已经过了中午,团队甚至还没开始处理他们当天的长列表待办事项!走出应急模式后,很难在任何有趣的事情上取得进展。
另一种说法是,我们总是让紧急事务阻碍了重要事务。更危险的是,我们破坏了对数据的信任。数据科学团队最终陷入防守而非进攻的境地。
我亲眼见过这种情况很多次。在 COVID-19 大流行初期,我被要求帮助加利福尼亚州了解疾病可能带来的影响。那是一个全员参与的时刻,我们可以访问到令人难以置信的资源和数据集。然而,我们仍然在质疑仪表板上基本数字的准确性,比如 ICU 床位的可用数量或某个医院剩余多少防护装备。为了追踪问题,我们不得不使用类似于printf语句的方式来调试数据何处出了问题。不幸的是,我们没有办法运行诊断来回答那些带有重大后果的非常简单的问题。
仪表板和决策只是皮毛问题——那么人工智能呢,尤其是生成式人工智能呢?尽管存在很多兴奋点,有时似乎我们忽略了基础知识以及数据质量有多么重要;我们不能像典型软件那样检查和调试 AI 系统。虽然这里的机会巨大,但风险也同样巨大,而在没有数据质量控制的情况下操作黑盒模型是一种可怕的前景。
数据科学家和工程师认识到这些问题本身就是一种成就,因为这意味着我们已经进入了数据利用的下一个阶段。第一阶段是数据的民主化。现在我们正在使用数据!而使用数据也带来了巨大的责任,我们需要数据团队更好地控制自己的命运。这种类比就像工程师拥有的工具,比如可观察性平台、值班系统、QA 环境、DevOps 工具等。数据从业者应该拥有必要的工具,让他们能够提前解决数据问题的根本原因。这就是这本书要讨论的内容。
要写一本真正优秀的技术书籍,你需要有亲身经历。Jeremy 拥有从事数据质量工作的伤痕,不仅在一个组织,而是与许多团队和跨不同行业和领域的利益相关者合作。此外,他还是该领域公司的创始人(完全披露,我也是投资者)。他们深入了解堆栈上下的所有问题,包括所有文化、政治和技术动态。解决数据可观察性问题的人是那些对问题有着不可思议的同情心的人,这正是你在这里找到的。
我对读者的建议:不要觉得第一遍就要一口气把这本书读完。相反,快速浏览一下,了解大致内容。就像处理数据集一样。你可以玩弄它,看看有什么内容和你感兴趣的地方,然后随着时间的推移深入了解。你可以分段应用这本书,消化它,并在面对特定问题时参考它。毫无疑问,你会想一次又一次地回到这些页面。
DJ Patil,博士
GreatPoint Ventures 的普通合伙人
前美国首席数据科学家
前言
大多数公司在达到足够的规模和规模后,会开始质疑他们的数据是否可信。他们在仪表板上看到的数字显然不可能是准确的;突然间,机器学习模型在生产环境中表现不佳。内部开始流传“垃圾进,垃圾出”的说法,指的是使用可能包含损坏、缺失片段和其他不准确性的数据构建产品和功能的问题。
当公司数据的信任开始下降——或者可能从一开始就不存在——解决这个问题至关重要。数据质量并不是随着公司继续增长而神奇地改善的东西;事实上,由于增加的复杂性,它只会变得更糟。数据质量与软件质量一样,需要持续监控,以便在问题出现时快速修复。
许多组织在理论上赞同这个想法,但在实践中难以在企业规模上实施数据质量监控。当 Jeremy 和 Elliott 在 2018 年创立 Anomalo 时,正是因为他们亲身经历了这些挣扎,他们意识到现有的数据质量监控方法无法满足现代企业的需求。
在公司仅维护少量、受控制的小表时,编写检查每个表和每个列必须满足的每个业务逻辑规则可能是有效的,但随着当前数据量的增加,这种方法感觉像是在海洋中开展煮海水的工作。跟踪关键绩效指标可以为您提供有关数据质量的重要信号,观察基本元数据,如数据是否按时到达,也可以做到这一点——但仍然覆盖不足,您将无法捕捉到所有未曾考虑过的问题。
这就是为什么我们对这本书中将分享的方法如此兴奋:用机器学习自动化数据质量监控。ML 是一个无比强大的工具,正在各个地方推动创新,数据质量领域也不例外。在本书中,我们分享了五年来构建的 ML 驱动数据质量监控平台的知识,该平台被各种行业的企业客户广泛使用。这些章节包含我们所知的最前沿技术——无论是关于如何开发无监督模型来检测数据中的问题,如何进行基准测试和调整该模型,还是如何确保您的通知不会太嘈杂。
如果你决定投资这项技术,现在很可能不会太早。数据通过更好的决策、自动化和生成式人工智能,推动了技术变革的最新迭代。你的数据质量最终决定了你的组织产品和服务在这个新的、不断变化的景观中的影响力。当企业能够构建更好的技术时,我们所有人都能感受到集体创新的好处——无论是经济上、社会上,还是个人层面的影响。
所以,提高你的数据质量,也许能拯救世界?也许这有点夸张。但我们确实认为,你会从这本书中学到一些东西,并希望在这过程中享受乐趣。
最后我们想说:数据质量是一个持续的旅程。现在在这个领域有大量的创新,我们期待未来还会有更多的创新。也许作为读者,你甚至会将本书中的技术进一步发展——这是我们的希望,如果是这样的话,我们很乐意听到你的想法。你可以直接联系作者:automating.data.quality.monitoring@anomalo.com。
谁应该使用本书
我们撰写本书时主要针对三个主要受众。
第一个是首席数据与分析官(CDAO)或数据副总裁。作为负责组织数据的高层,整本书都适合你,但你可能对第 1、2 和 3 章节最感兴趣,我们在这些章节中清楚地解释了为什么你应该关注在你的组织中自动化数据质量监控,并详细讲解了如何评估自动化数据质量监控平台的投资回报率。第八章节同样非常相关,因为它讨论了如何随时间跟踪和改进数据质量。
本书的第二个受众是数据治理主管。在这样或类似的角色中,你很可能是直接负责管理组织数据质量的人员。虽然整本书对你来说都非常有价值,但我们认为关于自动化的章节,第 1、2 和 3,以及关于集成和运营的第 7 和 8 章节,将特别有用。
我们的第三个受众是数据从业者。无论您是数据科学家、分析师还是数据工程师,您的工作都依赖于数据质量,您使用的监控工具将对您的日常工作产生重大影响。构建或运营数据质量监控平台的人员应特别关注第四章到第七章,我们将讨论如何开发模型、设计通知,并将平台与您的数据生态系统集成。
本书中使用的约定
本书使用以下排版约定:
斜体
指示新术语、URL、电子邮件地址、文件名和文件扩展名。
等宽字体
用于程序列表,以及在段落中引用程序元素,如变量或函数名、数据库、数据类型、环境变量、语句和关键字。
此元素表示提示或建议。
此元素表示一般注释。
此元素表示警告或注意事项。
O’Reilly 在线学习
超过 40 年来,O’Reilly Media一直为公司提供技术和商业培训、知识和见解,帮助它们取得成功。
我们独特的专家和创新者网络通过书籍、文章以及我们的在线学习平台分享他们的知识和专长。O’Reilly 的在线学习平台提供即时访问的实时培训课程、深度学习路径、交互式编码环境,以及来自 O’Reilly 和其他 200 多家出版商的大量文本和视频。更多信息,请访问https://oreilly.com。
如何联系我们
请将有关本书的评论和问题发送至出版商:
-
O’Reilly Media, Inc.
-
1005 Gravenstein Highway North
-
Sebastopol, CA 95472
-
800-889-8969(美国或加拿大)
-
707-829-7019(国际或本地)
-
707-829-0104(传真)
-
support@oreilly.com
我们为本书创建了一个网页,列出勘误、示例和任何额外信息。您可以访问https://oreil.ly/automating-data-quality。
有关我们书籍和课程的新闻和信息,请访问https://oreilly.com。
在 LinkedIn 上找到我们:https://linkedin.com/company/oreilly-media
在 Twitter 上关注我们:https://twitter.com/oreillymedia
观看我们的 YouTube 频道:https://youtube.com/oreillymedia
致谢
如果没有许多人的贡献,这本书是无法完成的。Anomalo 的 CEO 兼联合创始人 Elliot Shmukler 在书中的创新和发现过程中分享并发现了许多创意,他是一个不可或缺的审阅者。Anomalo 的成立团队成员和我们的应用机器学习经理 Vicky Andonova 也在这本书中开发和完善了许多理念。来自 Anomalo 的其他内部审阅者包括 Anthony Lee,Amy Reams,Erick Peirson,John Joo,Lucy Vallejo-Anderson,Taly Kanfi 和 Tristen Cross,他们提供了出色的建议和反馈。这本书也不可能在没有所有 Anomollamas(这里没有提及的许多人)的创造力和洞察力的情况下完成。谢谢你们。
我们还要感谢其他顾问和朋友,包括:著名数据科学顾问 Monica Rogati;Faire 的联合创始人 Daniele Perito,他创造了数据伤痕这一术语;Discover 的企业数据平台高级总监 Prakash Jaganathan,他提供了早期评审并允许我们链接到他出色的投资回报案例研究;Chick-fil-A 团队,他们为我们的平台入驻过程提供了宝贵的见解;DJ Patil 在推广我们的早期发布中的贡献;Josh Wills 的幽默和见解;以及 Josie Stanley 分享她的艺术才能。
我们要特别感谢 O’Reilly 团队,包括我们不可思议的编辑 Gary O’Brien 和我们的图书制作与管理团队:Aaron Black,Jonathon Owen,Elizabeth Faerm,Carol Keller,Kristen Brown,Lisa LaRew,Patrick McGrath 和 Phil Garzoli。我们还要感谢我们的 O’Reilly 技术审阅者,Oscar Quintana,Pier Paolo Ippolito,Shubham Piyushbhai Patel 和 Wayne Yaddow,他们通过提供重要的评论和问题,改善了书籍内容,并带来了行业专业知识和外部视角。
第一章:数据质量的重要性
2022 年 3 月,Equifax 正在将其数据从本地系统迁移到新的云基础设施,这是一个众所周知的棘手过程。在此过程中,引入了一个错误,影响了信用评分的计算方式。大约 12%的公司信用评分数据受到影响,成千上万的人最终得到了与实际情况相差25 分或更多的评分。由于不知道错误的存在,消费 Equifax 数据的贷款机构改变了他们提供给客户的利率,甚至拒绝了本应被批准的贷款和抵押贷款申请。
不幸的是,这并不是最近在新闻中曝光的唯一数据质量问题。
-
在 2020 年,数据错误导致英国近 16000 例 COVID-19 阳性检测结果丢失,可能导致 50000 人未被告知自我隔离。
-
所谓的航空公司“错误票价”,有时会无意中打折超过 90%,迫使航空公司要么亏损,要么因为无法兑现这些“故障价格”而损害他们的声誉。
-
Facebook 向一群社会科学家提供了一个数据集,其中遗漏了其所有美国用户的一半,影响了研究社交媒体对选举和民主影响的学术工作的结果。
-
视频游戏公司 Unity 在从第三方获取的糟糕训练数据后,其 AI 广告系统损失了 1.1 亿美元。
这些新闻报道展示了特别严重的数据质量问题可能带来的影响,但这并不是全部。绝大多数数据质量问题从未被发现,正在偷偷地损害公司的价值,就像你现在阅读这些内容一样。而那些被发现的问题中,很少有公开披露的。
如果你曾经在数据团队工作过,下面这两个轶事可能会让你感同身受:
-
有一天,一家大型科技公司的产品仪表盘显示出净推荐者分数(NPS)调查结果的突然下降。这很可能意味着客户对产品变更感到不满,因此在整个组织中引发了警报。高级领导层介入,并成立了一个工作组。工程师和分析师评估了过去一个月内的所有代码更改,并彻底检查了他们的所有用户数据,以找出可能导致分数暴跌的原因。
数据科学家分析 NPS 数据最终揭示了根本原因。在他们的分析中,他们发现最新结果中评分为 9 或 10(满分为 10)的数据完全消失了。这导致工程团队进行了调查,他们发现 NPS 调查嵌入的 iframe裁剪了最高的 NPS 响应值,因此顾客在物理上(或者我们应该说,在数字上?)无法选择 9 或 10。
-
一个顺风车公司建立了一个机器学习模型,用于检测潜在的欺诈新乘客账户,并自动阻止它们注册。他们的模型依赖于第三方信用卡数据。在其他事情之间,模型发现当来自第三方的数据为空时,欺诈可能性更高;这表明这些人使用的信用卡可能不合法。
一切都很顺利,直到有一天,第三方出现了数据质量问题,导致它发送 NULL 数据的频率比以往更高。没有人注意到这个错误,公司继续使用机器学习模型进行欺诈预测。这导致许多新用户被拒绝注册公司的服务,因为他们被错误地分类为欺诈账户。
我们打赌,每位与数据打交道的读者都有过类似的经历。当数据处理得当时,它会释放出令人难以置信的价值。但如果你的数据没有经过质量保证,就像试图用可能被污染的食材经营餐厅一样。你可能会幸运地不会有人生病,但有时候,你的顾客和你的业务可能会遭受损失,可以肯定他们不会再以同样的眼光看待你的食物了。一项研究发现,91%的 IT 决策者认为他们需要改善公司的数据质量;77%的人表示他们不信任公司的业务数据。
是否有办法恢复对数据的信任?您能否确保我们刚提到的这些问题能够立即被检测出来并迅速解决,避免任何其他人(尤其是当您处理大量复杂数据时)受到影响?
我们相信答案是肯定的,并且解决方法是通过机器学习自动化您的数据质量监控。本书将帮助您发现自动化数据质量监控的力量。您将学习如何实施一个平台,以确保高质量、可信赖的业务数据。
高质量的数据成为新的黄金
感觉像是昨天,企业还在努力从孤立的数据库中提取数据。Apache Hadoop 使得可以在大规模和复杂数据集上运行更高级的查询(如果你知道该如何操作)。尽管如此,在不久的过去,数据通常局限于一小部分事务系统——一个“围墙花园”中的关键资源,受到严格控制,访问受到限制。
几年间,云数据仓库/湖和数据转换工具迅速改变了我们处理数据的方式。现在,组织接触的每一片信息都被记录并存储。组织中的任何决策者都可以(a)查看交互式仪表板或报告来用数据回答问题,或者(b)直接查询数据。建立在数据基础上的机器学习系统正在为业务决策提供信息或自动化,并推动新产品的发展。
“我们坚信未来的 10 年将是数据的十年,”2022 年硅谷投资公司安德森·霍洛维茨如是写道。媒体喜欢称数据为新石油和新黄金。我们认为这类说法应该有一个重要的注解:只有数据本身是高质量的时候才是正确的。坏数据比根本没有数据更糟糕。
为了理解为什么会这样,让我们来看看围绕数据发生的一些趋势以及为什么质量在每种情况下都是成败的关键因素。
数据驱动的公司是今天的颠覆者。
常见的说法是,今天增长最快、最成功的公司都是软件公司。但仔细观察,它们实际上是数据公司。
以亚马逊为例。他们不仅仅是通过拥有世界一流的软件工程人才建立了全球最大的零售平台。他们通过找到如何利用数据进行个性化推荐、实时定价和优化物流来实现的。再举一个行业的例子,Capital One 是美国第一批将其数据从本地系统迁移到云端的银行之一。他们通过使用数据来个性化营销和做出更智能的信贷决策,成功区分并加速了他们的增长。
无论您看金融服务、商业、数字媒体还是医疗保健,数据和软件的交汇处是竞争的前沿。然而,如果企业使用的是低质量的数据,员工自己都难以信任,那么他们将无法做出好的决策,更不用说彻底改革一个行业了。如果您的数据质量基础不牢固,那么投资新的数据科学、机器学习和生成式 AI 项目就会是一个错误。
数据分析已经民主化。
渴望跟上颠覆者的步伐——或者成为颠覆者的一员——公司正在要求每个团队更加数据驱动。他们已经将分析专家嵌入功能单元(营销、增长、财务、产品团队等),以推动更复杂的数据使用来进行决策:我们能否拉取客户过去的浏览和购买活动统计数据,以便我们编写更贴合的电子邮件?我们能否查看我们的高级用户如何接受最新功能,以确定我们的发布是否成功?
现在有大量的工具让分析师——或者说是跨职能团队中的任何人——能够自助回答与数据相关的问题,而无需编写任何代码。他们可以在几秒钟内启动一个仪表板或报告,这在不久之前可能需要工程师一个月的时间来构建。为了支持这些分析需求,数据不再由一个小而集中的团队维护,也不再作为整个业务的统一事实表可用。相反,数据分散并由更广泛的人群管理,这些人更接近业务线。
如果没有高质量的数据,我们所见到的是,民主化对数据工程团队来说会成为一场噩梦。他们被积压的问题淹没,并时刻警惕着下一个紧急事件。与此同时,组织的其他部门越来越怀疑数据。启发式和直觉再次成为常态。最终,如果数据缺乏信任,民主化分析就是在浪费时间。
AI 与机器学习的差异化
许多公司将 AI/ML 列入他们的路线图,因为它能够以个性化和自动化交互的形式创造令人难以置信的价值。机器学习(ML,我们将其与 AI 互换使用)依赖于先进的统计模型,根据数据中称为特征的历史信号来预测未来。凭借足够的特征数据和合适的建模技术,AI 可以优化或个性化与业务关心的任何实体(消费者、内容、交易等)的频繁交互。
数据质量决定了 ML 模型的成败。您必须确保自己拥有用于训练和推理的高质量数据集。如果生产中使用的数据与它们训练时看到的数据分布相匹配,模型通常表现良好。但是,当出现远远超出它们以前看到的数据分布的数据时,模型往往会彻底失败。(与人类相比,人类可以使用更高级的智能从一个领域或分布泛化到另一个,并考虑到与常规显著偏离的情况。)
生成式 AI 与数据质量
谈到差异化:生成式 AI 又如何?这些模型与传统 ML 不同。它们不是基于从结构化数据中提取的特征进行预测,而是直接摄取原始的非结构化数据——就像从消防水龙头中饮水一样。
如果企业越来越依赖生成式 AI,数据质量仍然重要吗?答案明确是肯定的。提示需要整合来自业务的结构化数据(例如客户信息)。如果您使用这些模型自动化业务的部分流程,您需要追踪该自动化并确保通过高质量的日志一切如预期般运行。而且,即使生成式 AI 达到或超越了期望,我们始终需要能够信任我们聚合、计数和分析的数据,就像时间和金钱一样。
此外,组织提供给这些生成式 AI 模型的非结构化数据仍然存在数据质量问题。这些问题使用传统的数据质量监控方法更难找到,需要自动化的 ML 或 AI 来识别。这使得本书中涵盖的技术作为确保新生成式 AI 应用程序使用高质量输入的基础显得更加重要。
公司正在投资现代数据堆栈
没有提及现代数据堆栈的数据趋势概述就不完整(尽管我们真的等不及这个术语被淘汰,坦率地说!)。如今,一套正确的软件即服务(SaaS)供应商可以完成 10 年前一支 100 人的全职数据工程师团队可以完成的工作。企业正在从传统的本地存储迁移到云系统,这些系统让它们比以往更轻松地利用更多的数据。

图 1-1. 现代数据堆栈。
现代数据堆栈是一项重要的投资。当数据质量工具被忽视(如图 1-1 所示)时,这项投资就会受到损害。特别是因为迁移经常是数据质量问题的主要来源,组织在升级后常常面临数据状况不佳的情况(见章节“数据迁移”)。在每个人都在学习新系统的绳索的情况下,问题的根本原因更难追踪。
数据越多,问题越多
在前一节中,我们解释了推动企业比以往任何时候更依赖高质量数据的趋势。不幸的是,如今要获得高质量数据比以往任何时候都更加困难。复杂性更高,发生得更快,而且缺乏有效的防护措施。这是同一硬币的两面:进步与痛苦。在本节中,我们将探讨导致数据质量下降的一些最重要因素。
要了解可能发生的具体数据质量问题类型的分类,请参阅附录 A。
数据工厂内部的问题
传统上,仓库一直是公司内部数据系统运作方式的比喻,强调货物的存储和运输。但随着现代数据堆栈的兴起和公司处理数据的新方式,这个比喻已经不再完整。相反,我们建议如今的公司正在操作更接近数据工厂的环境:一个复杂的环境,用于将原材料转化为有用的产品。
我们摄入的是流式数据集、数据库的副本、SaaS 应用程序的 API 提取以及数据源的原始文件,而不是钢铁、橡胶和电子产品。工厂建立在云数据仓库和数据湖的基础上,而不是水泥。在这种情况下,在工厂楼层操作的机器是像 Matillion 和 Fivetran 这样的 ETL 工具,像 Apache Airflow 这样的编排平台,以及在 dbt、Apache Spark 和 SQL 中进行的转换。操作这些机器的人员是现代数据团队的数据工程师和分析工程师。而生产的产品,不是消费品或工业品,而是支持业务用户和数据专业人员决策的精选数据产品,支持 ML 算法的训练和预测,以及直接输入其他数据系统的数据流。
物理工厂中可能出现的所有问题在数据工厂中也可能出现。Figure 1-2 提供了一个概述。

图 1-2. 数据工厂及工厂楼层可能出现的问题。
机器故障
数据处理或编排工具可能完全崩溃,停止或降低数据的流动。
调度错误
数据处理作业可能以错误的顺序运行或以错误的节奏运行,导致数据丢失、计算不正确或重复数据。
原材料质量差
由于上游问题,输入工厂的原始数据质量可能较差,其不良影响可能在整个数据仓库中传播。
部件错误
SQL、Spark 或其他处理和操作数据的代码可能会引入错误,导致无效的连接、转换或聚合。
设置不正确
工程师可能在配置复杂数据处理作业时出错,这可能导致各种问题。
升级失败
尝试升级代码、应用程序版本或整个子系统可能会引入微妙但普遍存在的数据编码或转换方式的差异。
通信失败
为添加新功能或功能而进行的善意更改可能与其他受影响团队的沟通不畅,导致数据处理逻辑不一致,从而产生质量问题。
数据工厂内部的问题通常是数据质量问题的最常见源头,因为它们直接影响数据的流动和内容(而且在生产数据环境外部很难进行测试)。
数据迁移
随着公司寻求跟上最新和最伟大的基础设施,数据迁移越来越频繁。这包括从本地数据仓库到云提供商(例如从 Teradata 到 Snowflake),从一个云提供商到另一个(例如从亚马逊网络服务 [AWS] 到谷歌云平台 [GCP] 或反之),从一个数据库到另一个数据库(例如从 PostgreSQL 到 AWS Aurora),或从一个数据库版本到另一个数据库版本(例如 Elasticsearch 集群迁移)。
所有这些迁移都容易出现数据质量问题。让我们来看看从本地数据仓库迁移到云/SaaS 提供商的情况。许多公司有非常复杂的数据管道,源自传统的主机遗留系统,这些系统被转移到日益陈旧的本地数据仓库中。这些传统系统已经存在数十年,并且随着增加新功能、团队的变动和业务需求的变化,累积了大量的增量复杂性。
当将这些错综复杂的数据处理和存储迁移到云端时,公司试图复制在本地环境中所做的工作。但是在云端重新创建本地流程可能引入非常微妙的问题,导致重大的数据质量后果。
例如,我们与一家公司合作时提到,他们客户的出生日期在这样的迁移中被严重破坏(在图 1-3 中可视化)。在他们的传统主机上,出生日期存储为从某个参考日期(如 1900 年 1 月 1 日)偏移的整数。在导出时,这些整数然后被转换为新的云数据仓库中的日期。这看起来很简单,除了无人知晓的是,云数据仓库自动使用了 Unix 时间戳参考的 1970 年作为偏移量。所有的出生日期都被推到了遥远的未来。
与许多数据质量问题一样,后果是在后来默默发生的。公司有一个市场应用程序,根据客户的年龄发送电子邮件。一旦这个应用程序指向新的云数据仓库,直到有人注意到问题之前,没有客户收到任何电子邮件。(市场团队经常因为数据质量差而承受很大的痛苦。一项调查发现,营销人员在数据问题上浪费了其总预算的 21%。)

图 1-3. 当存储在本地数据仓库中的数据迁移到云数据仓库时,可能会出现不一致的情况,例如在计算客户出生日期时涉及不同的参考日期。
第三方数据源
使用第三方数据——即来自公司外部的数据——比以往任何时候都更容易和更普遍。举例来说,当 Jeremy 在 Instacart 时,定期收集的第三方数据包括:
-
天气数据用于需求预测/调度
-
用于路由的地图信息第三方服务
-
消费品包装(CPG)产品目录数据,用于丰富用户搜索和购物体验
-
欺诈倾向评分数据,以避免退款
-
零售商库存数据,用于确定每个店铺在特定时间内货架上的商品情况
经常情况下,第三方数据被编码为两个合作伙伴之间的数据关系:公司 A 和公司 B 必须共同合作为客户 X 提供服务或实现操作 Y,并且需要交换数据。有时,这被称为第二方数据。
在其他情况下,您正在使用公共数据或由第三方服务提供商打包的数据,以在一对多的关系中重新销售,通常用于对您了解有限的实体(客户、公司、位置)做出决策。如果您浏览在线目录Demyst上的公开可用信息源,您会发现只需点击几下即可利用全面的税收、财产和商业数据。
第三方数据是数据质量问题的常见来源。这不仅因为提供者可能会出错,还因为他们经常对其 API 或数据格式进行更改。除非您已经明确制定了数据合同,否则第三方不一定会考虑到他们的更新可能会如何影响您的具体用例,也不一定有义务提供通知或减轻措施。
公司的增长和变化
我们认为几乎所有数据最初都是高质量的。当产品首次构建和装配时,由构建它的工程师捕获的关于该产品的数据通常与他们的意图和产品功能非常一致。
但数据并不孤立存在。在现实世界中,公司不断调整和改进其产品,这反过来影响这些产品所产生的数据。这就像热力学第二定律一样:数据的熵随时间总是增加的。随着时间的推移,以下因素导致数据质量下降:
新功能
新功能经常扩展系统捕获的数据范围。在这种情况下,“添加额外列”的风险不大。但是,在某些情况下,新功能可能会替换现有功能,这通常会对系统产生的数据产生突然的影响。在许多情况下,新功能可能会改变数据的形状。粒度级别可能会增加——例如,数据现在可能在项目级别而不是整个产品级别进行捕获。或者以前的单一消息可能会被分解并重构为多条消息。
Bug 修复
根据卡耐基梅隆大学 CyLab 可持续计算联盟的数据,商业软件的平均每 1000 行代码中包含 20-30 个错误。Bug 修复可能会与新功能产生相同的影响。它们也可以真正改善数据质量,但当这种突然的改善对依赖数据的系统造成“冲击”时,可能会产生负面后果(请参见“数据冲击”部分)。
重构
重构发生在团队希望改进应用程序背后代码或系统结构而不改变功能时。然而,重构往往会带来意外的变化风险,尤其是对于像数据捕获这样在应用程序代码中可能没有经过严格测试的东西。
优化
经常情况下,简单地为了提高应用程序的速度或效率而进行更改。在许多情况下,数据捕获方式可能会成为性能问题,而更改可能会影响系统发出的数据的可靠性、时间粒度或唯一性。
新团队
新团队经常继承一个旧应用,并且对其与其他系统的交互方式或者所产生的数据如何被消费的理解有限。当他们对产品进行更改时,他们可能会无意中打破其他团队对其现有期望,引入数据质量问题。
停机
除了有意的变更,许多系统会简单地发生停机,即它们停止正常运行或者在服务水平下降的情况下运行。在这些停机期间,数据捕获通常完全丢失。这通常并非是数据质量问题本身,因为数据缺失反映了停机期间活动的缺乏。但在许多情况下,停机可能会影响正在发出的数据,而不影响服务本身,这是一个数据质量问题。
外生因素
当您利用数据进行决策或构建产品时,总会有影响数据的因素是您无法控制的,例如用户行为、全球事件、竞争对手行动以及供应商和市场力量。请注意,这些并不是数据质量问题本身,但它们通常看起来和感觉起来像是数据质量问题,并且可能需要类似的处理方式。
例如,在某些行业中,公司根据竞争对手的实时数据做出自动化决策。电子商务公司监控竞争对手的价格数据,并且几乎可以立即调整其价格。航空公司也是如此。在这些情景中,如果竞争对手突然、急剧地改变了他们的行为,该业务也会立即做出相同的改变,并且在其数据中出现大幅度的变化。对公司来说,及时了解这些变化非常重要,因为这些变化并不总是期望的或者故意的。
任何关于外生因素的讨论都不应忽略 COVID-19 疫情。在分析用户行为时,每个人都不得不将 COVID-19 的前几个月视为特殊情况。例如,图 1-4 展示了有关芝加哥出租车行程里程数的数据在 2020 年 3 月份发生了显著变化。

图 1-4. 芝加哥出租车行程的平均长度在 2020 年 3 月份急剧下降。出租车数据可以从芝加哥市官网公开获取。请查看此图的完整版本https://oreil.ly/adqm_1_4。
在 COVID-19 期间,机器学习模型必须快速重新训练以应用新的数据,因为基于历史趋势的假设不再适用。在一个著名案例中,Zillow 用于预测房价的模型——这个模型支持 Zillow Offers 的新业务部门——无法及时适应变化的市场。这项自动化服务为未能在变化的市场中出售的房屋支付了过高的价格,导致 Zillow 不得不裁减员工数达其总数四分之一。
团队通常发现自己处于以下两种情况之一,涉及外部因素:
-
在某些情况下,例如 COVID-19,外部变化足够剧烈,以至于您需要提醒决策流程,并可能重新训练您的 ML 模型。这几乎就像数据质量问题——这是一个您希望立即被通知的变化,以便您可以进行损害控制。
-
在其他情况下,外部因素对您的决策有更微妙的影响,例如供应链问题影响您的订单处理时间。您需要快速理解这些变化的背景,并排除任何可能看起来像真正外部趋势的数据质量问题。
为何我们需要数据质量监控
随着高质量数据的日益重要,以及数据质量问题比以往任何时候都更加普遍,您可能已经被说服改善数据质量的重要性。但是,您应该如何考虑这样的举措呢?它是否作为一次性修复——在几个月或几个季度内将您的数据整理到位,并让事情顺利进行?
这种方法通常适用于软件,但对数据来说则不然。代码今天和明天一样,除非有意进行更新。您可以在受控的 QA 环境中进行测试,并运行仅隔离系统的单元测试。一旦测试通过,您基本上就完成了。
另一方面,数据是混乱且不断变化的。它依赖于您无法控制的外部因素,比如用户实时与产品的交互方式,因此您真正只能在生产环境中进行整体测试。您的测试必须能够过滤掉所有噪音——而真正的数据质量信号中有很多噪音。
出于这个原因,虽然软件错误通常通过自动化测试和用户反馈很快被检测和修复,我们坚信大多数数据质量问题从未被捕捉到。因为团队缺乏适合数据的正确持续监控工具,问题会默默发生并被忽视。
更糟糕的是,随着问题发生后经过的时间增加,修复数据质量问题的成本急剧增加:
-
可能导致问题的潜在变化数量随着评估时间的增长呈线性增加。
-
团队对为何进行变更或该变更可能带来的影响的背景了解数量随着变更时间的增长而减少。
-
“修复”问题的成本(包括回填数据)随着问题首次出现以来的时间增加而增加。
-
长时间存在的问题最终会变成其他下游系统的“正常行为”,因此修复它们可能会导致新的事件。
当引入一个事件然后稍后修复时,它实际上有两种不同类型的影响。我们称之为数据疤痕和数据冲击。
数据疤痕
事件发生后,除非数据被极其细致地修复(通常不可能或昂贵),否则它将在数据中留下一个疤痕。我们最早听到这个术语是由 Faire 的首席数据官兼联合创始人 Daniele Perito 使用的。疤痕是指一段时间内给定数据集的一部分记录是无效的或异常的,并且在未来对这些记录进行操作的任何系统中都无法信任。
数据疤痕将影响机器学习模型,因为这些模型必须适应在疤痕期间学习数据中不同的关系。这将削弱它们的性能,并限制它们从疤痕期间捕获的所有数据中学习的能力。它还会削弱模型对受疤痕影响的特征重要性的信任—模型会低估这些输入的权重,错误地认为它们在数据集中的普遍性较低。即使您设法回到过去修复疤痕,也很容易在下游的机器学习应用中引入所谓的数据泄露,因为无意中在修复过程中包含了当前状态信息。这会导致模型在离线评估中表现非常好(因为它可以访问来自未来的“时光旅行”信息),但在生产环境中表现不稳定。
数据创伤还会严重影响此数据集上进行的任何未来分析或数据科学工作。它们可能导致更复杂的数据流水线,难以编写和维护,因为数据用户必须添加大量的异常处理以避免由创伤引入的偏见。这些异常可能需要在包括来自创伤时段数据的任何报告或可视化中予以记录和解决,从而增加任何试图解释数据或从中做出决策的人的认知负担。或者,创伤可能需要从数据集中完全移除,导致该时期的“数据健忘症”,这可能会影响趋势分析或基于时间的比较(例如,这个统计数据的年度对比结果是多少?)。
数据震荡
除了造成的创伤效应外,在生产中还会出现数据质量问题引入时以及数据问题修复时的效应。这就是我们所说的数据质量“震荡”,它还会影响到人工智能/机器学习和决策制定。
当数据质量问题首次出现时,任何使用从数据派生特征的机器学习模型都将突然面对完全不同于它们训练过的数据。这将导致它们被新数据“震惊”,它们为受数据质量事件影响的任何观察结果常常产生极不准确的预测。此震荡会持续到模型使用新数据重新训练为止,而这在持续部署模型中通常会自动发生。
然后,一旦数据质量问题得到修复,实际上这将给模型带来另一种震荡(除非数据在历史上得到修复,这通常是不可能的)。修复带来的震荡往往与数据质量问题引入时的初始震荡一样严重!
对于分析/报告用例,这些震荡通常表现为指标或分析突然发生意外变化。当观察到这些变化时,它们常常被误认为是真实世界的变化(这些报告的整个目的是反映现实情况),因此会改变运营或者做出其他决策,以应对数据质量问题,就像它们是真实的一样。而当修复发布后,同样的情况可能会反向发生。
数据质量问题修复的时间越长,创伤越深,修复时的冲击也越大。

图 1-5. 演示随着时间累积,如何侵蚀数据质量和信任。每个条是事件留下的数据创伤。每个 X(标记事件首次发生时)代表一个数据震荡。值得注意的是,每个对号(解决事件 2 时)也是一个数据震荡。
允许伤疤和冲击继续积累的后果是,随着时间的推移,数据的客观质量逐渐下降。图 1-5 说明了事件如何堆积,以至于每个人都确信数据质量低且数据本身不可信任。填充数据已经很难,而建立信任更加困难。
因此,组织在思考如何应对数据质量不佳时需要进行框架变革。这不应该是一个一次性的项目,只是为了处理给定数据源的数据质量问题。相反,它应该是一个持续的数据质量监控倡议,可以在发生数据质量问题时及时发现并尽快解决。
没有数据质量监控,问题将不会被发现,直到业务用户、数据专业人员或机器学习算法或其他系统的客户注意到为止。以这种方式运行数据工厂,相当于在没有任何质量控制过程的情况下运行生产消费品的工厂。
自动化数据质量监控:新的前沿
当今的数据专业人员正在经历领域内令人兴奋、令人惊讶的变化。无论是投资于生成式人工智能,还是在整个企业中实现分析民主化,或者从传统数据库迁移到云端,几乎每家公司都在尝试一些前所未有的数据处理方式。
因此,对于大多数企业来说,现在是投资于数据质量的最佳时机。随着数据使用的增长,数据质量问题的风险和负面影响也在增加。数据质量是需要不断监控并通过尽快解决问题来维护的事项。
有效的数据质量监控并非易事,特别是对于大型企业来说,拥有成千上万张表和数十亿条记录是很常见的。虽然人工手动检查数据行不通是显而易见的,但使用像为数据编写测试和跟踪关键指标这样的传统解决方案也不适用。你可能希望为最重要的表格做这些工作,但对整个数据仓库实施这些工作是不可行的。
在本书中,我们将向您介绍使用无监督机器学习自动化数据质量监控的概念。这是一种具有多种好处的新技术。它几乎不需要手动设置,并且可以轻松扩展到您的数据仓库中。通过正确的实施,它可以自动学习数据变化是否足够大以信号质量问题的适当阈值。它可以检测到广泛的问题,包括那些没有人想过要为其编写测试的未知未知。
使用 ML 也带来了自己的挑战。构建模型本身就是一项复杂的任务,但你还需要确保它能在各种真实世界的数据上运行,而不会过度或不足报警。您将需要建立通知系统,帮助您的团队有效地处理问题,并与您的数据工具包集成,使数据质量成为组织的重中之重。您还需要制定长期部署和管理监控平台的计划。
不用担心——我们将在你前行的道路上提供所需的建议和工具。我们认为利用 ML 自动化数据质量监控与过去几年发生的任何数据创新一样令人兴奋,也是现代数据堆栈中最重要的突破之一。希望通过本书的学习,您也能认同这一观点。
第二章:数据质量监控策略及自动化的角色
有许多不同的方法可以用来处理数据质量监控。在评估选项之前,思考成功的标志很有帮助。在本章中,我们将定义成功的要求。然后,我们将详细讨论传统策略——手动检查、基于规则的测试和指标监控——以及它们的测量结果。
接下来,我们将探讨自动化数据质量监控的概念。我们将解释无监督机器学习如何帮助我们满足成功标准的一些缺失方面,将监控扩展到大量数据,并减少警报疲劳。
最后,我们将介绍本书中提倡的数据质量监控策略:一个四柱结构方法,结合数据可观性、基于规则的测试、指标监控和无监督机器学习。正如我们将展示的那样,这种方法有许多优势。它允许主题专家(SMEs)强制执行基本约束,并跟踪重要表格的关键绩效指标(KPIs)——所有这些同时为大量多样化数据提供基础级别的监控,而无需服务器农场或大量分析师。
监控要求
为了解决第一章中概述的各种问题,一个成功的数据质量监控策略必须在四个维度上交付成果(如图 2-1 所示):
-
第一,它必须检测所有重要数据的质量问题,以便您可以确信没有任何问题被忽视——无论这些问题出现在表格、列还是单个行的级别。
-
第二,当出现真正问题时,它必须及时向相关人员发出警报,同时避免由于非问题而导致警报疲劳。
-
第三,它必须帮助您迅速和高效地解决问题。(要查看这些问题的完整列表,请参阅附录 A。)
-
最后,它必须扩展以监控企业范围内数据的健康状况。

图 2-1. 数据质量监控解决方案应跨越检测、警报、解决和扩展四个维度取得成功。
数据可观性:必要但不充分
在讨论数据质量监控方法之前,让我们先了解一下数据可观性。这是任何全面的数据质量战略的关键部分,其重要区别在于数据可观性监控关于你的表格的元数据,而不是数据内容本身。
数据可观性类似于基础设施或网络可观性,但应用于数据仓库中的数据。换句话说,它解答以下问题:
-
这个表格还存在吗?
-
表格的模式有任何不利的变化吗?
-
最近是否更新过表格?
-
表格中的数据量是否与我的预期一致?
当确定您是否可以信任您的数据时,这些是重要问题。您会注意到在 附录 A 中的一些数据问题仅通过可观测性就可以检测到。
那么,数据可观测性是如何工作的呢?幸运的是,它使用的元数据可以从大多数现代数据仓库中收集,甚至无需查询表格。通常有一个 API 使得这些数据可用,或者可以查询的系统视图保持这些数据的更新。所需的数据包括表级统计数据,例如:
-
表格
-
最后更新时间
-
行数(或字节大小)
以及列级信息如:
-
表格
-
列名
-
列类型
平台只需要定期(例如每小时)捕获可观测性元数据,然后可以回答关于元数据如何随时间变化的问题。
例如,在 Snowflake 中,您可以使用以下查询检索表级元数据:
SELECT
TABLE_NAME,
ROW_COUNT,
BYTES,
LAST_ALTERED
FROM INFORMATION_SCHEMA."TABLES"
当涉及“最近是否更新过表格?”时,系统需要做出艰难的决定:什么是“最近”,什么时候延迟变得显著?有些表格使用流数据进行持续更新,有些每小时更新一次,还有些可能一天多次更新,或者仅多次更新每周(或每月、每年)。时间序列模型(如侧边栏中讨论的 “时间序列度量监控” )在这里是一个强大的工具——它们可以利用更新历史来预测下一次更新到达的预期上限。
类似的事情也必须做出来决定数据量“是否与预期一致”。时间序列模型可以观察数据量的历史,并识别最近更新是否异常低。一旦解决了这些问题,数据可观测性可以应用于数据仓库中的成千上万个表格。
这是否意味着您解决了数据质量问题?当然不是!数据可观测性检查只涉及数据通过您的仓库的流动。它们不解决数据内容是否高质量的问题。仅使用数据可观测性就像在运营一个水处理厂,您的唯一质量控制是提供的水压——完全不关心这些水是否适用于饮用! 表格 2-1 重申了数据可观测性和数据质量监控之间的主要区别。
表格 2-1. 数据可观测性和数据质量监控之间的差异
| 数据可观测性 | 数据质量监控 | |
|---|---|---|
| 它回答了什么问题 | 数据是否及时通过我的仓库? | 我的仓库生成的数据是否高质量? |
| 它是如何工作的 | 目录元数据 作业监控
数据血统 | 查询数据 需要专家或 ML
解释性至关重要 |
| 为什么需要 | 捕捉数据的移动失败 | 对数据值进行深度监控 |
|---|---|---|
| 主要缺点 | 忽视数据的内容 | 难以扩展 |
数据质量的传统方法
许多团队发现,对整个数据仓库实施数据可观察性相对容易,但在扩展数据质量监控方面却遇到了困难。在历史上,团队通常通过手动检测、基于规则的测试和指标监控来监控数据质量。虽然我们在这里单独介绍了这些策略,但组织通常同时采用这三种策略的混合方法。每种策略都有其价值,但在规模化时也存在显著的缺陷。
手动数据质量检测
自数字数据问世以来,人们已经有可能通过手工查找潜在问题,但这越来越困难。
在某些企业中,存在一个有意的手动数据质量审查流程,无论是抽样检查、审查总结还是查看可视化数据。这通常对于监控数据质量是不够的。当数据足够小且简单,以至于人类可以查看电子表格并迅速发现潜在问题时,手动检查可能是有效的(顺便说一句,各种研究报告称,近 90%的电子表格存在错误!)。但是,在规模化时,这种方法并不有效。此外,手动过程本质上是主观的。将同一复杂数据集分别交给 10 个不同的分析师,他们对所评估数据质量的结论可能会大相径庭。
手动数据质量检测也以一种截然不同的方式发生:偶然发现。有人在处理数据时,突然“发现”了一个数据质量问题。以下是一些例子:
计算汇总统计数据并将其与已知数据或其他参考数据点进行比较
例如,数据科学家可能会发现,在聚合数据集中,客户数量比另一个已知来源高出 50%,这表明可能存在数据质量问题。
创建可视化图表以总结数据,清楚地显示数据质量问题
例如,关于缺失值的时间序列可视化可能显示最近几周出现了非常明显的增加。
从分析结论或模型询问中得出的结论,这些结论实际上是不可证明的。
分析人员可能会发现,过去三周欧洲新账户的增长超过了每周 1000%,但实际上这是不可能的。或者,一个机器学习模型可能会建议,预测用户流失的最重要特征是用户的出生日期,但仔细检查后发现,这是由于有很大一部分用户出生于 1970 年 1 月 1 日(Unix 纪元的开始,表明存在错误数据)。
依靠分析师和数据科学家在工作过程中发现数据质量问题并不是一个成功的策略。从业者只会定期检查数据,并且有特定的目的。他们很可能会在数据质量问题发生很久之后才发现,并且几乎肯定会错过超出项目范围的数据质量问题。
这种边做边解决的方法实际上相当有害。在我们合作的一些组织中,分析师花费的时间超过 50%用于调查和解决数据质量问题。这种手工作业不仅削弱了团队的效率,而且随着时间的推移,对士气造成了巨大的打击。
尽管如此,分析师和数据科学家总是希望能够看到他们处理的数据,并且根据情况,手动审查可以增加价值。人类能够将不同的数据源和背景知识结合起来,并以算法无法自动化的方式得出结论。此外,当在分析或 ML 模型的背景中发现数据质量问题时,它们从定义上就是“重要”的数据质量问题,需要解决——没有误报的风险。
最终,无论选择哪种监控方法,都应减少手工工作量,并使其能够扩展监控数据。然而,它仍应使人类能够轻松地对其数据进行概述和手动检测问题,并且您可以通过生成摘要统计信息和可视化来帮助此过程。
基于规则的测试
在测试软件时,工程师编写单元测试来调用组件,测量所采取的操作,并对这些测量应用确定性规则,以验证软件是否按预期工作。例如,电子商务应用程序可能有一种计算税率的方法。单元测试可以向此方法提供各种商品篮子和商店位置,并确保它产生正确的答案。
尝试将适用于测试软件的方法(编写大量单元测试)应用于数据是很自然的。我们称之为基于规则的测试。常见的基于规则的测试工具包括 Great Expectations 和 dbt。基于规则的测试是一种确定性测试,可以应用于特定来源的数据。数据要么通过测试,要么未通过测试;中间没有灰色地带。
例如,基于规则的测试包括:
-
表
ticket_sales中的列number_of_tickets从不为 NULL。 -
列
listing_time中没有来自未来的值。 -
列
price_per_ticket的平均值每天始终在 50 到 100 之间。 -
等式
number_of_tickets * price_per_ticket * (1 + tax_rate)对于表ticket_sales中的每一行始终等于total_price的结果。
每个规则都可以看作具有范围、类型和(通常)若干约束条件:
范围
规则适用于哪些数据?什么数据存储?什么表或视图?哪些列?在什么时间范围内?哪些具体行?
请注意,在大多数情况下,可以对给定数据集的每一行评估基于规则的测试,这允许您清晰地将“好”行与“坏”行分开。但规则也可以应用于从数据中计算的统计信息(例如,0 <= sum(column_x) <= 50)。通常,我们将讨论规则作为独立应用于每一行数据的情况。将规则应用于统计数据的特殊情况可以视为首先计算聚合数据集(可以由某个实体(如客户)、时间单位(如日期)或根本不进行任何分组)然后对该聚合结果应用基于行的规则。
类型
将应用的规则类型是什么?例如,对于适用于给定列的规则,可以从各种类型中选择:列是唯一的,列从不包含 NULL 值,列字符串值在指定集合内等。规则类型可以扩展到个别列之外,还涵盖表的元数据(上次更新时间,总行数),表的模式(特定列名、类型和顺序)等。规则可以涉及多列及其相互关系,或表如何通过联接语义与其他表关联(例如,在给定主键上的 1:1 联接)。
最复杂的规则类型通常表达为 SQL 查询,可能包括联接、子查询和寻找表中“永远不会出现”的条件的复杂语句。例如:“每个完成结账但后来未被取消、作废或完成的订单的客户应在customers_with_active_orders表中有记录。”
在 SQL 中可以表示为:
SELECT COUNT(DISTINCT customer_id) as num_missing
FROM orders
WHERE checked_out
AND order_status NOT IN ('canceled', 'voided', 'completed')
AND customer_id NOT IN
(SELECT customer_id FROM customers_with_active_orders)
约束
选择了范围和类型后,通常还需要对规则提供一些常量约束。例如,在规则“price_per_ticket始终介于 50 和 100 之间”中,50 和 100 的值是常量约束。在某些情况下,这些不是必需的(“列 X 是唯一的”不需要约束),或者它们与规则类型重复(“列不为空”等同于“NULL 计数等于 0”,其中 0 是常量)。
规则是任何数据质量监控策略的重要组成部分。与人工分析相比,规则运行成本低且不会出错。规则也清晰而确定。每一行要么通过要么不通过。一旦完全理解了规则,你也会理解为什么基于规则的测试会失败,以及为使该行的测试通过,必须满足什么条件。当基于规则的测试失败时,你可以信任它确实失败了——数据良好但规则说不好(当然,除非规则本身是错误的;我们稍后会讨论这点)。
此外,规则是识别从数据集开始就存在的或从历史上未被捕捉和解决的数据质量问题的最可靠方式之一。为什么呢?规则允许专家在其对生成数据的系统或收集数据的业务背景的知识基础上表达他们对给定数据集的要求。专家可以编写一条规则,说明数据的过去、现在或未来不应该为空。相比之下,那些从数据历史中学习的方法(例如使用指标或无监督机器学习来检测意外变化)则是在寻找数据中的突然变化,这些变化从定义上来说是新的,而不是历史数据质量问题。这样的方法无法判断数据是否一直存在问题。
规则还擅长于识别海量数据中的个别问题。如果您正在处理一个有数十亿行的表格,那么规则通常是发现少数违反给定条件的记录最可靠的方式。(请注意,如果您不关心每一条记录,这可能是一个负担,因为您将不得不找到方法来排除您不再关心但仍然违反规则的数据质量“疤痕”。)
然而,仅依靠基于规则的测试是错误的。首先,在指定高质量规则时存在很大的出错空间:
-
范围可能被过于狭隘地指定(
WHERESQL 子句太紧凑),导致规则忽略数据质量问题(例如,规则仅适用于表的 X 段,但也应适用于表的 Y 段)。 -
范围可以过于广泛地指定(
WHERESQL 子句太过宽泛),导致规则错误地将有效数据标记为无效(例如,对于某些记录,这列实际上应该是应该为空)。 -
规则的约束可能被错误地指定。在设置列值或统计数据的范围时,这种情况非常普遍。范围可能过于广泛(从而忽略真实的数据质量问题),或者过于狭窄(从而在数据变化时产生非常嘈杂的结果)。
-
可能选择了错误的类型规则。测试可能无法捕获用户的真实意图,或者因为测试不恰当而产生无意义的通知(该列始终打算具有 NULL 值,但仍然应用了“永不为 NULL”的规则)。
此外,仅用高质量规则覆盖现代企业的所有数据是一个劳神费力的任务。考虑以下现实的假设性例子,组织需要监控 10,000 张表格以检测数据质量问题:
-
公司整体依赖的 10 张关键事实表至关重要(董事会的关键统计数据来自这些表)。
-
公司每天在业务和运营决策中使用的关键数据包含在 90 张表中。
-
900 个表对于个别团队或倡议至关重要,每周由产品经理、ML 工程师、分析师、数据科学家或其他数据专家使用。
-
剩余的 9,000 个表可能会在其他 1,000 个表中以微妙且难以检测的方式显示数据质量问题。
每个表可能有数十、数百甚至数千列。例如,事实表通常将关于特定类型实体的各种信息聚合到一个非常广泛的表中,以启动许多分析和用例。有些表还可能有数百或数千个段(行的组合),具有不同的行为。例如,Web 事件表通常捕获大量关于各种不同事件或用户行为的结构化数据(设备、IP 地址、URL、用户、时间等)和半结构化数据(JSON 负载)。
每个表的每一列或数据段可能需要 5 到 10 条规则来覆盖数据的最重要约束条件。因此,要使用基于规则的测试监控它们最重要的表,一个组织可能最终会写入1,000 个表 * 每个表 50 列 * 每列 5 条规则 = 250,000 条规则。这还不包括半结构化数据、段变化或其他 9,000 个潜在重要的表!

在大型数据仓库中创建和维护数据质量规则是一项苦不堪言的任务(Josie Stanley 插图)。
除了创建基于规则的测试之外,您还必须维护这些规则,这比维护单元测试要困难得多。代码的单元测试应该在每次运行时产生相同的结果,直到有软件更新打破预期行为,无论是有意还是无意。但是与代码不同,数据不断以不可预测的方式变化——随着新产品的推出、宏观环境的变化或用户行为的改变等等。因此,基于规则的测试可能非常脆弱。为了确保它们的定义——特别是它们的约束——保持准确,规则需要在产品和数据演变过程中不断更新。在一开始放宽约束以节省时间可能很诱人,但这会冒着忽略真实问题的风险。
总结一下,基于规则的测试并非是在现代企业中监控数据的可扩展解决方案。然而,规则是中小企业表达和强制执行数据期望的有力工具。例如,图 2-3,来自 Airbnb 关于其数据质量战略的报告,提供了由中小型企业定义的规则的实际示例,以确保列表数据的一致性。理想的数据质量解决方案使得各种中小企业能够轻松创建、编辑和分析规则。

图 2-3. 从 Medium 文章“Airbnb 的数据质量”摘录,展示了 Airbnb 内部用来确保数据质量的验证规则和指标检查的示例。
指标监控
下一个数据质量监控方法也受到软件工程的启发。大多数软件系统通过跟踪有关基础设施的指标来进行监控,并在有突然不利变化时通知。这些统计数据可以涉及硬件本身(CPU 利用率、内存等)、网络活动(丢包等)或正在运行的个别服务(队列长度、平均延迟等)。
类似地,您可以监控有关数据的统计信息,并设置阈值,以告知系统在数据高于或低于预期时发出警报。挑战在于,对于数据质量来说,需要监控的指标范围广泛。为了确保适当的覆盖范围,您需要为每一列、段和可能关心的统计量(如 NULL 值百分比、重复百分比、均值、最小/最大值等)准备指标。
除了可伸缩性问题外,数据质量的指标监控还存在其他问题。首先,因为它在聚合统计水平上测试数据,可能会错过只影响少数记录的数据质量问题。此外,大多数指标监控的实现并不识别导致指标变化的具体记录,这使得理解指标变化的原因以及其是否合理(如外部趋势)或由于数据质量问题而起变得困难。
指标监控还可能忽略随时间积累的数据问题。例如,假设数据质量问题的根源是一个位于功能标志后面的代码更改。如果功能逐步推出到客户段,数据将逐渐变化。任何指标的变化也将很缓慢,并且可能永远不会达到警报的阈值。
尽管如此,当您希望密切关注数据的特定片段时,指标监控至关重要。例如,图 3-1 展示了 Airbnb 选择优先考虑的一些指标,如活跃列表数、新活跃列表数、重新激活和停用。这些重要指标通常受整体数据集的小部分子集的影响,这些子集中的任何趋势可能不会被考虑整体数据的其他监控方法捕获。
同样,指标监控可以帮助当数据在预期的一定比例记录中降级时,但用户希望避免该百分比显著增加时。例如,可能有 20%的时间,用户记录因为创建用户记录的方式而没有有效地址。如果这个百分比显著增加,那么可能存在一个数据质量问题,该问题影响了更多用户的地址信息,超出预期范围。
鉴于这些优缺点,一个成功的数据质量监控策略应该让用户在关键指标上设置监控,并理想情况下使用时间序列模型来设置适当的阈值。但仅依赖指标监控是不够的。
自动化无监督机器学习进行数据质量监控
在覆盖了传统(非自动化)监控方法后,现在是时候介绍一种新策略:无监督机器学习。数据质量与许多其他领域无异,这些领域的流程曾经完全手动,如欺诈检测、核保和产品推荐,现在可以由机器学习算法处理。这些算法允许更高效率地操作,并以驱动更好业务结果的节奏和一致性运行。
虽然我们将在第四章和第五章更详细地探讨无监督机器学习,并在此概述其作用及其在规模化自动化数据质量监控中的关键角色。
什么是无监督机器学习?
广义上,机器学习算法可以分为有监督和无监督两类。在有监督学习中,模型用于学习的数据是由人类标记的。图像分类器通常使用有监督学习——人类向模型展示成千上万张被标记为树、猫等的图像,模型随后学习识别新图像中类似的对象。在无监督学习中,模型没有人类标签,只有数据本身,包含所有数据固有的模式和关系。模型从数据本身学习,并根据迄今为止看到的一切来解释新输入。
作为数据监控策略,有监督学习在实际中并不实际,因为它需要人类收集和标记大量多样的训练数据,这些数据代表模型需要可靠检测的真实世界数据质量问题。考虑到数据从表到表、从公司到公司的巨大差异,收集足够的标记数据使有监督机器学习能够有效工作将是困难的。这使得无监督学习更适合监控数据质量。假设您已开发出效果良好的模型,它可以开始监控数据集而无需任何初始设置,并在数据变化时继续学习和适应。这些算法可以被调整以检测数据中的深层复杂问题,例如:
-
一组柱子中的 NULL 值的百分比已经增加。
-
特定数据段(例如一个国家)已经消失或到达的记录比预期少。
-
在柱子中的分布发生了显著变化(例如,信用评分的分布偏高于预期)。
-
多列之间的关系发生了变化(例如,这些列过去相加等于彼此,但现在对于一部分记录不再是这样)。
我们注意到一些数据质量监控解决方案声称正在进行“机器学习”,但实际上只是依赖于时间序列模型来监控许多指标。根据使用的技术,时间序列模型可能在幕后使用 ML,但其范围狭窄,仅仅是试图预测序列中的下一个指标值。它无法分析基础数据,也不会发现不直接影响正在监控的指标的数据质量问题。在本书中,我们将使用无监督学习这个术语来指称在整个复杂数据集中检测到意外变化的更广泛挑战。
无监督机器学习最强大的一个方面之一是,它旨在理解表中数据的关系变化作为一个整体。这一点非常重要,因为表中的数据通常是高度相互关联的。

图 2-4. 台湾信用卡违约支付数据集中列之间的关系(UCI 机器学习库)。查看此图片的完整尺寸版本,请访问https://oreil.ly/adqm_2_5。
图 2-4 中展示的信用卡数据集是一个很好的现实世界的例子。每个柱子出现在垂直和水平轴上,圆圈的颜色基于柱子之间的phi-K 相关性进行着色。¹ 这揭示了数据集中柱子之间关系的许多信息。看看靠近对角线的黑色圆圈的集群,你会发现pay_N, bill_amt_N和pay_amt_N列彼此之间存在相关性。还有更多令人惊讶的关系。例如,age与limit_balance以及marital_status强相关。但marital_status与limit_balance之间的相关性较弱。
在监控数据质量时,我们往往会过于简化事物,仅考虑单独列中的值、分布或摘要统计,并创建规则或指标来监视单独列。但实际上,现实世界的数据具有我们在这个信用卡数据集中看到的丰富而复杂的相关结构。这对监控有两个重要的影响:
-
如果我们使用度量或验证规则分别监控这个数据集的每一列,那么我们的监控器也会高度相关。如果列之间的相关性与某些数据或过程有因果关系,那么底层机制的变化可能会导致许多依赖的度量值同时改变,验证失败。因此,我们可能会收到数十个或更多的警报,而不是一个警报。
-
如果我们仅仅评估每列数据质量的话,将忽略大量可能对数据质量非常重要的上下文信息。在信用卡的例子中,如果突然发现
age和limit_balance的相关性较小,这可能表明其中一列经历了突然的数据质量问题。
为了充分利用现实世界数据集的丰富结构,避免为相关问题发送过多警报,并成功实现规模化的自动化数据质量监控,我们需要一种能够对整个表中的数据进行操作而不是单独对每列进行操作的监控方法。
这正是无监督机器学习算法的设计目的。与更窄范围的指标或验证规则相比,一个好的模型将发现更广泛的数据质量问题,包括人类未曾考虑到的未知未知。它将自动抑制重复的异常;在问题再次发生的第二天,它将能够将第一天作为“新正常”的基线。影响多列的问题可以被聚类在一起,并作为单一问题呈现;它们通过无监督算法的一次遍历被检测到,并相应地分配到适当的列和行中。
类比:车道偏离警告

使用 DALL-E 生成
当我们思考数据质量监控如何通过机器学习自动化时,脑海中浮现了一个类比:驾驶从完全手动变为由机器学习算法辅助的过程。这些算法之所以如此宝贵,是因为它们可以考虑到大量的上下文信息,这些信息可能对于人类来说太隐蔽或太复杂,无法通过硬编码、规则和阈值逻辑来捕捉。
考虑驾驶的一个方面:确保您的车辆保持在车道内并进行安全的车道变换。如果我们将讨论过的数据质量方法应用于这个问题,我们可能会得到以下结果:
完全手动方法
驾驶员只需注意车道标线,从不分神或在驾驶时意外入睡。这就是我们一直以来确保车辆保持在车道内的方式。这需要驾驶员高度的注意力和集中力,但仍然会发生与车道偏离相关的事故。
基于规则和度量的系统
想象一种依赖规则和指标的方法,考虑使用车载摄像头和一些基本统计数据来检测道路上的车道线。如果进入摄像头的像素中有一定百分比是黄色(基本上是一个指标阈值),那么车辆就会触发警告。这将是灾难性的,因为许多车道标线不是黄色的,也不是实线或足够大来触发这个阈值。此外,道路(或其他表面)上会有许多标记可能看起来是黄色的,但与车道线无关,导致误报。
此外,有许多情况下驾驶员应该跨越车道线,例如左转或变道以避开交通或障碍物。在实际操作中,这种过于简化的系统可能会导致过多的干扰性、无用的通知,使驾驶员禁用车辆的警报机制——回到默认情况下没有通知的状态。
机器学习方法
机器学习方法应用于车道偏离警告,能够更智能地判断是否发送通知。它会利用车辆的上下文,避免在转向灯开启时发送通知——或者当物体检测系统发现车辆前方有障碍物,并且车辆应该偏离车道时也不发送通知。它还可以优先提醒用户,只有在跨越车道时有高风险遇到其他车辆或障碍物时才会发出警报。
这种方法比简单的车道通知系统噪声要少得多,因此用户更有可能听从它。这显著提高了车辆和用户在驾驶时的安全性和满意度。
自动化的局限性

图 2-5. 随着自动化程度增加而创建的价值图示。
重要的是要仔细考虑机器学习自动化的使用案例。设计不良的自动化往往比没有自动化更糟糕。这就是为什么我们在本书的大部分内容中致力于开发一个在真实数据上表现良好,并避免用警报压倒用户的模型。
如图 2-5 所示,超过一定程度的自动化也会有收益递减。即使您拥有强大的模型,也会有无监督机器学习无法解决的问题。首先,因为它在对数据进行采样时,永远无法像验证规则那样找到针对三个列之间关系必须始终为真的情况。例如,如果说关系必须始终为真,而即使是单个记录违反了该约束,规则也能找到它——而在无监督学习中,可能根本不会对其进行采样或认为它不重要。
其次,无监督模型在定义上是在寻找数据中的新变化,永远不会捕捉到历史上一直存在问题的事物。例如,想象一下,一个代表客户拥有的车辆数量的列在创建时被错误编码,使得缺失值被编码为0而不是NULL。这会导致下游系统认为拥有零辆车的客户比实际情况更多,实际上,只是这些客户的数据尚未收集到。无监督模型或时间序列度量监视器将无法捕捉到这个问题,因为数据中的关系随时间并未发生变化。
第三,无监督模型将每列和每行视为同等重要——因此可能不会像直接定义在数据上的度量那样密切关注数据的某个切片。例如,如果您正在监视列等于某个值的百分比的次数,则这些记录对度量结果的影响要大得多,而对于无监督监视方法来说,它们将不会那么重要,因为后者看待的是整个表格。
自动化规则和度量的创建
自动化是否能够使用算法来自动创建规则和度量是一个自然的问题。尽管自动规则和度量监控是可能的,但这非常昂贵,并且会导致假阳性和假阴性(未检测到的问题)。
规则
假设您想要自动为您的数据质量监控系统创建规则,而不是要求专家手动指定规则。您可以从预定义的常见规则类型(唯一性、NULL 值、正则表达式模式等)开始。然后,您可以对一些历史数据进行抽样分析。对于每个事先定义的规则,您可以检查表中的每列,以确定样本数据是否满足该规则。然后,您还需要检查所有历史数据,以确保规则继续通过。最后,您可以对所有历史数据上通过的规则进行生产。听起来不错,对吧?嗯,不完全是这样。
对于包含大量数据的表格,这种方法可能会非常昂贵,因为最终需要对每个历史记录评估每条规则,以避免未来频繁失败的情况。对于数据量较小的表格,规则会非常脆弱——许多规则可能仅仅是由于偶然才通过的。而且每次数据发生变化时,您都需要编辑规则或重新运行自动设置过程。最后,大多数用户希望的真正重要的规则需要使用 SQL 进行定制,以便仅适用于表格中的部分记录,或者表达列或表格之间复杂的关系。这些定制很少会成为系统预定义规则类别的一部分。
在实践中,我们没有看到这种方法在现实世界中起作用。我们建议您让最终用户可以轻松地自愿添加规则,使用他们自己的首要原则判断,用于需要数据完美的情况。这有两个优点。首先,只创建真正重要的规则,减少误报和随时间需要维护的规则数量。其次,如果新规则在历史数据上失败,这将成为一个学习机会。最终用户可能会找到并修复历史数据质量问题,或者在揭示为何规则失败时了解数据结构的新内容。
指标
自动化指标创建意味着,与要求用户手动选择要监视的特定指标相比,系统会自动计算和监视每个表和列的一组指标。
这将非常容易实现。您可以决定您认为大多数用户会关心的开箱即用指标。对于表格来说,这可能是每天的记录数和表格上次更新时间。对于列来说,这可能是记录的空值、零值、空白值或唯一值的百分比。更进一步,您可以配置每个指标仅寻找不利事件——行数减少、空值数量增加等。
提前定义一些指标自动监控的方法,帮助用户立即了解其表格数据质量的一些见解,这是我们在 Anomalo 使用的策略。但请注意,即使是少量指标,这种解决方案也可能非常昂贵,因为您需要对每个需要监控的表格和每个列进行大量计算。除非您有假阳性抑制策略,否则也可能导致警报疲劳——单一的基础数据质量变化可能导致 10 个列出现空值增加,这将呈现为用户需要处理的 10 个单独警报。
尽管可以自动化一些指标,我们认为让用户能够定义自定义指标至关重要。这确保了不会错过重要的段落,可能出现轻微但关键的变化需要跟踪。它还允许您捕获对用户最重要的指标——通常涉及计算用例特定统计数据,例如满足多列约束条件的记录百分比,这些数据在完全自动化的方法中会被排除在外。
数据质量监控的四支柱方法
我们在本章中涵盖了广泛的监控策略。总结一下,组织可能采取的不同方法如下:
-
什么都不做(呀!)。
-
为您的数据仓库实施数据可观察性(基本要求,但您实际上并没有完全监控数据质量)。
-
使用手工制定的规则或度量监视数据的一个小子集。这会忽略未知的问题(您没有意识到需要检查的问题),并且仅覆盖数据的一小部分。
-
使用手工制定的规则和度量监视所有数据。这在设置和维护时间上非常昂贵,导致嘈杂的警报,并且还会错过未知的问题。
-
使用规则自动化监控。这非常昂贵,非常脆弱,并且仍然会错过大量分布和相关性问题。
-
使用度量自动化监控。这也非常昂贵,非常嘈杂,并且仍然会错过大量记录级问题。
-
仅使用无监督监控自动化。虽然这提供了良好的覆盖率,但不能捕捉所有问题,并且不会像手工制定的规则和度量那样密切关注关键数据。
-
(我们的建议)采用四柱方法。您可以以较低成本在整个数据仓库中实施数据可观察性。同时,对于数据质量,自动化的无监督机器学习可以提供明显问题和未知未知的基础覆盖。您的平台应该使中小企业能够通过低代码验证规则和时间序列度量监控最重要的数据和关系,从而非常容易地增强自动化监控。
数据可观察性、基于规则的测试、度量监控和无监督机器学习可以结合使用,以实现之前提到的检测、警报、解决和扩展的目标。这种策略可以高效覆盖真实数据质量风险,同时最小化误报和警报疲劳,而无需专门解决这个问题的分析师团队。
图 2-6 解释了这种策略的四个组成部分如何平衡彼此的优势和劣势。图 2-7 展示了规则、度量和机器学习在一些基本示例数据中的能力。

图 2-6。全面自动化数据质量解决方案的四个支柱。

图 2-7。不同策略如何检测数据中不同类型变化的示例。请注意,这是一个简化的示例,无论是显示的数据还是检测到的问题范围。
本书的其余部分是关于在您的组织中自动化数据质量监控的指南,按照我们在这里描述的四柱方法。我们将首先确保这种方法适合您的组织,并且投资回报率(ROI)对您和您的数据团队是合理的。然后,我们将涵盖建模策略和权衡,然后转向关键功能,如通知和集成。最后,我们将分享如何在您的组织发展过程中继续维护和增强您的数据健康。
¹ Phi-K 相关性类似于传统的相关方法(如斯皮尔曼或皮尔逊相关性),但可以用于不同类型的数据(数值和分类),并捕捉非线性关系,同时对于双变量正态分布的行为与皮尔逊相关性相同。
第三章:评估自动化数据质量监控对业务影响
通过机器学习自动化数据质量监控,您可以超越传统方法,如度量监控和基于规则的测试。但在深入讨论此方法的实施细节之前,我们想先解决可能存在的疑虑(或至少在页面上)。是否值得?
我们不会假装这个问题有一个唯一的正确答案。我们也不会告诉每个人明天就去建立或购买自动化数据质量监控平台。但我们可以帮助您回答诸如以下问题:
-
最适合自动化数据质量监控的数据类型是什么?
-
在我们投资之前,我们的数据堆栈应该是什么样子?
-
如何衡量新的数据质量监控方法的投资回报率?
数据质量问题是不可避免的(见下文侧栏)—但您选择的解决方案并非如此。本章结束时,您应该具备所有必要的工具,以进行对组织从自动化方法中获益的自我评估。我们将涵盖您应考虑的四个关键因素:您的数据、您的行业、您的数据成熟度以及您的利益相关者如何受益。然后,我们将提供有关如何通过 ROI 分析评估利弊的见解。
评估您的数据
您的数据及其特征可以告诉您很多关于自动化数据质量监控如何(以及是否)满足您公司需求的信息。多年前,IBM 提出了“大数据的四个 V”概念:体积、多样性、速度和真实性。它仍然是一个有用的框架,如原始信息图所示。以下是我们对这四个方面及其对自动化数据质量监控的影响的解释。
体积
如果数据量足够小,那么人们可以手动审查它。但即使每天只有几十条新记录,也可能需要进行自动化数据质量监控。当每天的数据行数接近百万或十亿时,挑战在于找出数据小但重要的部分中的数据质量问题——这使得投资于无监督学习模型和避免警报疲劳的通知变得至关重要(这是我们将在未来章节讨论的方面)。
多样性
组织捕获的数据种类越多,数据质量问题的风险表面积就越大。多样性的来源包括:
-
数据的结构如何
-
数据是如何收集的
-
数据中时间的测量方式
-
数据更新的方式
-
数据中描述的实体是什么
-
数据中的记录如何与其他记录相关
-
描述的业务过程的变化
-
数据的粒度或摘要程度如何
对于不同类型的数据,您关心的监控内容通常会发生变化。例如,考虑一下列可以通常被分类为标识符列、时间列、分段列或度量列。在每一类数据中,您可能关心的监控事项都不同——我们在这里列出了最重要的几项:
标识符列(例如,客户 ID)
需要监控的内容:唯一性,格式,关系完整性
时间列(例如,事件时间戳)
需要监控的内容:粒度,顺序,到达时间间隔
分段列(例如,客户地区)
需要监控的内容:有效性,分布,基数
度量列(例如,每日总订单)
需要监控的内容:平均值,分布,异常值
数据多样性的一个重要方面是结构。您的数据有多结构化将极大地影响您可能想要应用的监控策略。通过合适的技术,即使是非结构化数据,您也可以自动化数据质量监控。但通常来说,数据结构化程度越高,使用自动化方法进行监控就会越容易。
非结构化数据
非结构化数据可能包括视频、图像、音频和文本文件。在处理非结构化数据时,您将需要额外的算法来“解码”其内容,以获取您可以监控的值。
一种方法是计算关于非结构化数据的元数据(例如视频的长度、图像的大小)并监控该元数据以检测数据质量问题。为了更直接地监控数据值,您有时可以训练一个 ML 分类器——例如,您可以想象训练一个计算机视觉模型来检测模糊图像。
或者,您可能已经有一个使用数据作为输入的深度学习模型,例如通过摄取大量非结构化文本学习预测序列中下一个词的模型。如果您希望尝试在输入数据中找到问题,您可以通过监控模型的嵌入来监控:N 维数值向量,代表输入数据。通过使用无监督的 ML 方法监控嵌入中的漂移,您可以通过代理监控输入数据的变化。
然而,每次模型重新训练时,其嵌入会发生巨大变化。因此,这种监控策略仅对静态深度学习模型有效。随着基础模型的崛起¹,这些模型是用于文本和图像处理的大规模深度学习模型(如 OpenAI 的 DALL-E 和 GPT-4),这些嵌入在主要版本升级之间是稳定的,因此监控您的非结构化数据在这些嵌入空间中如何变化是一个有用的建议。
理解您的非结构化数据在嵌入空间中如何变化的意义和影响仍然是一个具有挑战性的问题。然而,解释个体神经元的新突破可能会使这变得更加容易。此外,组织可以将他们的结构化数据与非结构化数据嵌入关联起来,以表征其数据的哪些部分正在经历显著的变化。例如,可能会发现显著的分布变化仅限于特定地理区域的客户或来自特定平台的产品体验。最后,您可以随时返回文本本身,检查那些异常的样本,甚至可以要求生成式 AI 模型总结这些异常记录的样本。
半结构化数据
半结构化数据没有固定的平面表结构;其结构可能随时间而变化并且可以是嵌套的。但它确实有一个结构(例如标签和位置值),这些结构强制执行其元素之间的某种层次结构或关系。要自动化监视半结构化数据,通常需要混合使用模式验证、定制算法和规则。
许多类型的领域特定数据——例如地理数据或 DNA 序列——属于这一类别。但到目前为止,半结构化数据最常见的类型是 JSON 数据。特别是在公司较少成熟时,工程师通常会将数据存储为 JSON:每条记录都可以具有自定义模式,以捕获个别数字事件或用户配置文件的特殊性,并且随着时间的推移,此模式可以迅速变化,因此无需不断进行迁移结构化数据存储。
对于 JSON 数据,您需要考虑如何监视两个概念:对象或*{"key": <value>}*对,以及数组,由括号括起来的值列表。在最复杂的情况下,您将同时具有对象和数组的嵌套组合。
JSON 对象可以作为数据表中给定列的附加列轻松扩展。假设一个列json包含值{"name": "bob", "age": 32}。该列可以扩展为一个包含“bob”的字符串json.name列和一个包含32的整数json.age列:
json [json] |
json.name [string] |
json.age [integer] |
|---|---|---|
{"name": "bob", "age": 32} |
"bob" |
32 |
一些数据仓库将自动支持这种扩展并帮助您强制执行 JSON 的模式。但是,事先知道模式是不常见的(因为不同团队的工程师经常会更改模式或编写新的模式)。在这种情况下,您需要在监视之前扩展数据。
JSON 数组更难处理。您可以将它们视为已“压缩”为单行的数据的关系形式。例如,数组可用于指定客户的地址。
虽然你可以将这些列表展开为关系表,但你的选择并不那么吸引人:你需要将每个列表扩展为一个新表,带有客户 ID 列(根据每个客户的地址数量重复 1 到 N 次)和包含地址信息的地址字符串列(实质上是进行数据库标准化),如下所示:
customer_id [整数] |
address [字符串] |
|---|---|
| ... | ... |
这将使这些数据与其他客户信息隔离开来,使得难以看到地址问题与其他数据问题之间的相关性,并且使得使用其他客户信息来找到地址问题的根本原因变得更加困难。
另一种选择是将地址信息扩展为多个列(其中大多数列将是稀疏的,因为许多用户只有少量地址,但某些用户可能有很多地址),如下所示。这两种情况都不适合使用无监督 ML 进行监控:
customer.address1 [字符串] |
customer.address2 [字符串] |
... | customer.addressN [字符串] |
|---|---|---|---|
| ... | ... | ... | ... |
处理此类数据列表的一种策略是随机抽样数组元素,并监视这些元素以发现数据质量问题。此策略还允许你优雅地处理对象和数组嵌套的情况。我们将在第四章深入讨论抽样。
结构化数据
结构化的关系数据通常是最重要的监控数据类型,因为它是最经常被分析平台、ML 模型和其他数据产品消耗的形式因子。虽然它可能不占组织累积数据总量的大部分,但它构成了不成比例的有价值数据。在此类别中,有三种类型的结构化数据是你应该考虑监控的:标准化的关系数据、事实表和汇总表。
标准化的关系数据
在数据质量监控的背景下,你可以将标准化的关系数据视为分布在多个表中相互关联的数据(数据库标准化的确切定义和用途超出了本书的范围)。每个表都将有一个主键和与该主键唯一相关联的数据;每个表也可能有多个外键,可以用来与其他表进行连接。
此类数据在生产应用中非常常见。当在 OLTP(在线事务处理)模式下读取或写入数据库时,这是存储数据的最有效方式,每次应用程序交互都会生成与之相关的数据库读取和写入。许多数据仓库会将规范化数据直接复制到数据仓库中,作为存储在生产应用中的数据的原始“副本”。然后,这些数据将转换为事实表或汇总数据——“数据工厂”工作(参见章节“数据工厂内部的问题”),将数据转换为更适用于仪表板和其他数据产品的形式。
数据质量监控可以并且应该直接应用于规范化的关系数据,因为这些数据通常是下游问题“根源”的关键。然而,这些数据仅提供有限的监控表面,因为每个表都是狭窄且自包含的。要真正理解问题的范围和背景,数据监控解决方案需要与关系模型中的其他表连接——如果在查询时进行,这将是昂贵的。
事实表
为了克服将每个查询编写为多个规范化表的复杂联接和聚合的分析挑战,许多组织创建了“事实”表,将数据非规范化为一个单一的物化表。
例如,电子商务公司可能有一个fact_orders表,其中每一行代表客户在其网站上的一个订单。除了与该特定订单相关的时间戳和标识符外,它还可能总结其他表中的信息:
-
关于客户在订单之前采取的行动的信息(来自网页/移动事件表)
-
关于下订单的客户的信息(从客户表中合并)
-
关于订单中购买的商品的信息(从商品表中合并)
-
与订单的履行、取消或其他处理相关的时间戳(从订单处理事件表中合并)
这些表通常是监控数据质量问题时最具洞察力的。 事实表采用非常细粒度的信息,原本可能分散在数十或数百个表中,并将其汇总到具有实际业务价值的实体中。它们也专门设计和维护,以作为其他分析、机器学习和产品团队的集中基础。因此,在这个层面上可见的问题通常是重要的问题;它们可以通过无监督机器学习监控、基于规则的测试和指标监控的组合来发现。事实表还提供了大量关于表中每条记录的上下文,这可以帮助理解问题何时发生。
汇总表
摘要表是关系数据或事实表的聚合,通常用于支持仪表板和报告。例如,电子商务公司可能有一个客户摘要表,显示每位客户的最新统计信息,如订单数量、满意度评级和预期生命周期价值。或者,金融服务公司可能维护关键业务部门每日财务表现和风险信息的日汇总,用于生成财务报告。
这些表格对于监控数据质量问题至关重要,因为它们是报告应用程序的基础。一个微妙之处在于,这些表格通常只会显示每个实体的最新信息。因此,数据监控解决方案需要对这些表格进行快照,以便随时间检测到的问题。
速率
数据以各种速率收集、聚合和分发。例如,考虑每年生成的普查数据,与每毫秒生成的交易产品数据进行比较。
表格 3-1 显示随着数据更新频率的变化,监控数据质量问题的适当策略也在变化。
表格 3-1. 数据更新频率与监控策略的变化方式
| 频率 | 范围 | 示例 | 监控 | 解决 |
|---|---|---|---|---|
| 年 | 普查 | 大规模人口调查 | 手动 | 手动 |
| 季度 | 财务 | 季度财务报表 | ||
| 月 | 结算 | 每月结算周期报表 | ||
| 周 | 调度 | 零售业的每周调度数据 | 算法 | 人工审核 |
| 日 | 摘要 | 每日用户摘要统计 | ||
| 小时 | 上下文 | 医疗设备摘要统计 | ||
| 分钟 | 活动 | 广告归因数据 | 确定性 | 程序化 |
| 秒 | 事件 | 在线活动欺诈检测 | ||
| 毫秒 | 交易 | 信用卡批准流程 |
对于不频繁到达的数据,数据质量监控通常是一个手动过程。虽然可以使用机器学习模型比较不同时间段的数据集,但问题在于其相关性。当数据每年才到达一次时,模型需要多年时间来学习预期的变化——同时,生成数据的过程几乎肯定会发生变化,使模型的知识变得无关紧要。
对于每周、每日或每小时到达的数据,可以使用无监督机器学习进行自动监控,这既可能又强大。有足够的数据历史来训练模型,评估样本大小通常足够大以检测有意义的差异,并且频率开始变得过高,以至于无法在没有显著成本和负担的情况下由人类手动审查数据。
对于每分钟甚至毫秒级别到达的数据,监控考虑又有所不同。您需要能够通过程序响应实时纠正任何问题——涉及人类将会太慢。因此,尽管应自动监控此类数据,但仍需要更加确定性的解决方案(即仅基于规则的测试),以确保不存在误报的风险。
准确性
数据的准确性实质上是数据的真实性或正确性。我们无法真正知道数据是否准确地反映了现实世界,因此要对数据集的准确性进行良好的近似评估,您可以查看引入新数据质量问题的固有风险(见第一章)。您还可以考虑可能增加您对数据准确性信任的因素,例如数据生产者与数据消费者之间包含 SLA(服务级别协议)的合同,包括数据交付频率等。
您的数据源的准确性显然会影响您从数据质量监控中获得的价值。我们建议查阅第一章和附录 A,了解数据质量问题的示例及其发生原因,并将这些问题映射到您的业务中处理的数据类型。您还可以考虑审计您过去遇到的数据质量问题:数量、严重性等。
作为经验法则,以下数据源通常是最不可靠的:
-
尽管来自第三方的数据通常非常可靠,但其变化可能会出乎意料,而且未必与消费实体进行沟通。这通常是需要优先监控的数据。
-
由相互交互的非常复杂系统生成的数据更有可能遭遇数据质量问题,因为一个系统做出的假设可能不被其他系统尊重。
-
由正在持续变化和快速改进的系统生成的数据更有可能遭遇数据质量问题。
-
由传统系统生成的数据也更有可能存在问题,因为数据质量往往随时间而下降,并且这些系统通常未得到良好的维护。
特殊情况
在极少数情况下,某些类型的数据难以通过无监督的机器学习进行监控。在以下情况下,您可能需要手动或纯粹基于规则的方法:
-
数据的收集非常重要,尤其是需要手动输入的客户地址等个别数值。对于这种情况,您需要在输入时验证数据。如果直到数据进入数据仓库才发现问题,除非回头向客户再次确认地址,否则很难进行修复。
-
数据中实体或交易数量非常少。例如,金融公司有关并购的数据很难自动监控数据质量。这类数据数量不大,且交易形态和结构各异。
-
数据以单一的大型静态数据转储方式收集。例如,考虑来自制药试验的数据。如果试验持续时间较长,则可能需要进行数据质量监控,但在大多数情况下,这些数据是一次性使用相同的过程和系统收集的。如果存在数据质量问题,这些问题可能是数据固有的。您需要一个验证规则来发现这类问题,并将您对现实的预期与数据所说的进行比较。
评估您的行业
在 Anomalo,我们的客户主要来自以下行业:金融服务、电子商务、媒体、科技、房地产和医疗保健。虽然这一景观肯定会继续变化和发展,但我们对于为什么今天某些行业对数据质量的重要性感到如此迫切,进行了大量思考。
这部分是由之前讨论的数据因素造成的。所有提到的行业都与大量来自交易和事件的数据打交道。一些行业严重依赖第三方数据;例如,房地产公司依赖于来自多个合作伙伴的多列表服务(MLS)数据,这些数据的格式、及时性和质量各不相同。而在电子商务、科技和媒体等数字原生行业,平台和产品经常快速变化。
然而,还有一些额外因素可能会在推动行业采用自动化数据质量监控方面产生重大影响。
监管压力
毫无疑问,监管机构正在推动一些组织投资于自动化数据质量。例如,金融机构必须满足各种市场监管机构的监管要求,否则将面临重大的后果。例如,富国银行 在 2021 年因未能保护消费者免受不安全行为,被美国国家银行监督管理局处以 2.5 亿美元的罚款和法律约束同意令。花旗银行被罚款 4 亿美元,涉及企业范围内风险管理、合规风险管理、数据治理和内部控制方面的缺陷。
EDM 委员会是一个著名的全球性协会,提供企业数据管理及其与监管义务交叉相关的咨询和建议(所以不要寻找音乐推荐)。他们的云数据管理能力(CDMC)框架为处理敏感数据提供了最佳实践,并经常在金融机构中使用以确保合规性。该框架的关键方面包括:
CDMC 1.1
当关键控制合规性指标监测到低于特定阈值时,自动生成警报。
CDMC 1.2
确保数据目录中的所有权字段对于迁移到或在云中生成的敏感数据是填充的,并且如果创建了未填充此字段的数据资产,则通过分类工作流通知客户。
CDMC 5.2
必须为敏感数据启用数据质量测量,并在可用时分发度量。数据质量指标将使数据所有者和数据消费者能够确定数据是否合适使用。这些信息需要对所有者和数据消费者可见:
-
自动向数据所有者和数据消费者提供数据质量指标。
-
在数据目录中提供数据质量指标。
-
自动警报数据所有者有关数据质量问题。
CDMC 6.0
所有敏感数据必须提供数据血统信息。这至少包括数据在云环境中被摄入的源或创建的源。
很难想象如何在规模上实现这些保证,如果没有本书讨论的技术。
即使今天大多数行业中没有这种严格的水平,规定通常从最紧急的情况开始在孤立的背景下开始,并随着时间推移成为其他人的榜样。例如,过去只有医院工作人员经常洗手以保护病人;逐渐地,这开始包括其他群体,如食品准备人员,最终成为每个人的常规做法。特别是随着 AI/ML 的使用增长,我们想象数据质量将会越来越受到监管,因为它开始影响我们日常生活的更多方面。
AI/ML 风险
正如在第一章讨论的那样,当 AI/ML 模型在生产中使用的数据与其训练时的数据不匹配时,它们会表现不良。这很难调试,特别是因为数据质量问题通常不会以明显方式完全破坏模型,而是会使某些用户或场景下的表现变差。
如果你的组织正在构建模型,尤其是如果你将它们放在用户面前,那么你可能已经在数据科学、数据工程和 MLOps 方面进行了重大投资。如果没有将自动化数据质量监控作为 AI/ML 堆栈的一部分,这些投资将面临风险。为了说明这一点,让我们深入探讨由于数据质量问题在模型训练和推断期间可能发生的问题。
特征突发
图 3-1 展示了一种特征突发:一种影响 ML 模型特征的数据冲击。在单一天内,此特征的数据跃出了历史正常范围。这会对模型产生什么影响?

图 3-1. ML 模型数据中的特征突发。请在https://oreil.ly/adqm_3_1查看此图的完整大小版本。
如果在训练数据中使用,这种突发将导致该特征的重要性减弱,因为模型会认为该特征对未来预测的可靠性较低。如果这种类型的突发发生在生产环境中,你的结果将根据所使用的模型类型而变化。
线性模型根据定义进行线性外推。因此,如果你的特征突发是预期值的五倍,那么该特征将对结果分数产生五倍更大的影响。基于树的模型通常更具韧性。特征突发将倾向于将特征推向分布的极端端点。然后,模型将开始解释这些值与“通常”处于极端的任何群体是同义的。
神经网络在特征突发时表现得非常不稳定。它们在架构中具有复合的非线性特性,当数据突然移动到典型分布之外时,可能会产生异常行为。几乎无法预测它们的行为会是怎样的。
NULL 的增加
NULL 值的突增,在最好的情况下,对模型的影响与正常的特征突发相同。但在最坏的情况下,它可能以更加灾难性的方式影响模型。如果模型将 NULL 和零视为相同的方式处理,这种突增可能会使模型认为零值增加了,从而触发意外的行为。或者,如果模型聚合特征值,你可能会遇到 NULL 值叠加的问题。
想象一下,你有一张包含订单和订单中物品的表格,其中一个数据质量问题导致每十个物品价格中就有一个为 NULL。在某些平台上,如果计算物品价格的平均值,那些 NULL 值可能会主导聚合,导致每个订单的avg_item_price字段为 NULL,如果订单中有多个 NULL 物品的话。
相关性的改变
数据质量问题偶尔可能会改变列之间的相关性。例如,如果生成 ID 的方式出现故障,导致信用评分数据集错误地与贷款申请关联,那么结果的信用评分可能在分布上与正确值相同,但它们将不再与数据的其他特征(年龄、收入、信用历史等)相关联,也不会与未来的风险结果相关联!
当相关性突然改变时,结果行为将取决于模型的类型:
-
线性模型对特征之间的相关性非常敏感,尤其是如果它们没有很好地进行正则化(一种防止单个系数超过适当数值以适应数据的技术)。在这些情况下,相关性的变化可能导致模型预测出现较大偏移。
-
基于树的模型对相关性也非常敏感,因为它们通过逐列递归地对数据进行分区。相关性的变化将会使记录完全沿不同的路径进行路由,导致预测大幅波动。
-
神经网络会表现得不稳定,就像在特征突变时一样,因为数据分布突然开始进入一个空间(在多元意义上),而该模型并未经过训练。
重复数据
重复记录对于开发模型的数据科学家来说可能是一个主要问题。如果在创建训练数据集时错误地重复了数据,模型将在重复的信息上“过度拟合”,错误地认为它在现实中被过度表达。
在训练中,ML 模型学习将其参数“拟合”到训练数据集。然而,如果模型开始学习训练数据中的噪声,它可能会做得太好。这称为“过度拟合”。当构建机器学习模型时,数据科学家的主要关注之一是实现强大的泛化性能(避免欠拟合和过度拟合)。
另一个重复可能导致严重问题的地方是在拆分用于测试和训练的数据时。重复的记录很容易同时出现在训练数据和测试数据中。这将再次使模型“过度拟合”训练数据——在极端情况下,它可以简单地记住数据,因为相同的记录将出现在测试数据集中。结果是,模型看起来的表现比实际上好得多。
数据作为产品
当您将数据作为产品出售或打包时,您的数据质量就是您产品的质量,使数据质量监控对您的业务更有价值。一些公司直接提供数据作为服务。例如,金融服务中的信用聚合器、房地产中的 MLS 数据聚合器、投资中的上市公司财务表现数据以及电子商务中的竞争价格数据。
在其他行业中,企业并不一定在销售数据,但其数据仍然是产品提供中的重要组成部分。考虑媒体平台如何向内容创建者提供数据。这些创建者需要准确的指标,如观看次数和观看时长,以成功完成他们的工作,从而维护平台本身。如果在报告数据的方式上存在问题——也许是一个错误导致移动用户的双倍浏览被记录——这可能会对业务造成重大影响。
评估您的数据成熟度
随着组织的发展和成长,它们往往从“不成熟”的阶段,即刚开始收集数据,转向“成熟”的阶段,即构建人工智能和运行高级分析。在她的 Medium 文章中,我们的朋友和顾问 Monica Rogati 将此总结为“数据科学需求层次”。参见图 3-2。

图 3-2。数据科学需求层次(来自 Monica Rogati 的文章,“AI 需求层次”,Medium,2017 年 8 月 1 日)。
在数据成熟度的早期阶段,您开始关注数据可观察性的问题,这些问题可以通过监控表格元数据来回答。数据是否已被摄取?最近一次更新是什么时候?
当您继续向金字塔顶部发展,并达到那个中间层时,在这个阶段,您开始探索和转换数据,现在是考虑自动化数据质量监控的好时机。在这个阶段,您很可能已经积累了大量的数据,并且希望为聚合和优化的下一阶段创建一个坚实的基础。这些未来阶段将依赖于高质量的数据,以提高效率。
达到数据成熟度金字塔的中间阶段后,企业通常会感到他们缺少资源(分析师、数据工程师、产品工程师)来解决可能通过更广泛的监控发现的数据质量问题。因此,他们得出结论认为不应该投资于自动化监控。然而,我们认为这是一个错误。这些数据质量问题几乎肯定正在干扰他们现有的工作人员,并且正在积累一个越来越难以克服的债务。
与其避免了解问题(并感到有义务去解决它们),您应该建立能够识别问题并积极优先考虑哪些问题值得投资修复的能力。通常情况下,这意味着从少数关键表(如事实表)中开始,同意前期必须满足的标准,以便在这些表中投资于数据质量问题的修复。
不确定您在数据成熟度方面处于何种位置?您的数据堆栈是一个很好的指标。
当一家公司尚未采用云数据仓库时,通常表明他们对所收集的数据的使用还不成熟,现在自动化数据质量监控可能为时过早。在生产数据存储或云存储中的静止数据上构建强大的分析报告堆栈和数据驱动的团队文化非常困难。
一些公司在投资现代化云数据仓库之前就试图解决数据质量问题,但这通常是一个错误。
在生产数据库(Oracle、SQL Server、PostgreSQL 等)直接监控数据,可能会给本不支持此类大规模查询的存储系统带来沉重的分析负载,这往往会影响生产流量。有时公司会尝试在云存储格式中监控数据的数据质量(Amazon S3 等),但如果没有直接查询这些数据的平台,你能做的最好的只是监控文件的元数据(大小、格式、写入日期等)。一种常见的折中方案是建立数据湖仓架构,以便通过查询引擎如 Presto(或其托管版本 Amazon Athena)或 Databricks(通过 Spark SQL)按需监控数据。数据也可以从云数据仓库如 BigQuery 或 Snowflake 作为外部表进行监控。然而,每次监控运行都需要读取每个文件的全部内容(除非缓存),因此将这些数据加载到数据仓库中最终可能成本更低且性能更好。
数据成熟度的另一个指标是您的组织是否使用像 Airflow、Databricks Workbench 和 dbt 这样的工具,在数据仓库中进行转换、聚合和丰富数据。这些活动的存在通常表明需要进行数据质量检查,因为它增加了引入数据质量问题的风险。此外,这些服务通常希望通过 API 与数据质量监控解决方案交互,以在数据转换或发布后触发数据质量检查,或者在上游数据源未通过关键数据质量检查时等待处理下游数据。
最后,成熟度的最后一个指标是您的公司是否已经在数据目录上进行了标准化。当您有许多利益相关者访问广泛的数据时,数据目录非常有用;它们有助于识别哪些数据最重要。通常应该密切监控数据质量的就是这些数据。这里还存在一种协同效应,因为数据质量监控的结果可以复制到数据目录,并向用户展示,帮助他们了解数据是否经过了充分测试并且质量高。
评估对利益相关者的益处
随着组织在数据需求金字塔上的提升,它往往会拥有一个更大的数据团队,对数据质量监控解决方案的要求也更高。例如,大部分工程师组成的团队可能仅需一个 API 来监控数据质量,但随着非技术用户数量的增加,拥有一个用户界面来探索数据并传达关于发现的质量问题的更丰富见解变得越来越有价值。
当确定自动化数据质量监控是否适合您时,最好的起点是直接与您的利益相关者进行沟通。在接下来的几节中,您将找到组织中许多角色如何从自动化解决方案中受益以及他们可能感兴趣的功能类型的描述。
工程师
这些是数据工程师、分析工程师或数据平台团队成员。他们负责管理平台、ETL 管道,并更新数据的跟踪和存储方式。他们最关心的数据问题与数据流动的新鲜度和量、以及不同来源数据的对账有关。
很可能一个工程团队将被指定负责数据质量监控平台的技术实施。因此,他们希望能够轻松配置、尽可能自动化,并且与堆栈的其他部分简单集成。工程师们通常希望有一个强大的 API,允许使用以下一个或多个选项:
-
直接通过代码与 API 进行交互。这可以是直接调用端点,或者通过 Python 包。这是与 API 交互最灵活的方式,但不一定是最简单的方式。
-
在像 Airflow 和 Databricks Workbench 这样的编排平台中使用包。这些平台将基础 API 中的功能整合,并直接集成到编排平台中。这里是Anomalo Airflow 操作员的一个示例。
-
与在代码版本控制系统(如 Git)中管理的配置文件(例如 YAML、JSON)进行交互,并通过 API 与监控平台同步。这允许配置更改作为代码管理,但不如直接调用 API 灵活。
数据领导
数据团队经理通常希望通过高级分析来追踪整体数据质量的健康状况、其随时间的趋势以及用户如何参与平台。
经理们通常感兴趣的典型 KPI 包括:
数据质量覆盖范围
有多少表格定义了检查?这些检查的执行情况如何?领导者可以通过高层次的覆盖视图精确定位盲点。
数据到达时间
领导层需要能够识别表格的数据是否按时到达或符合 SLA。
数据质量趋势
快照统计数据并不足以追踪数据质量。管理者必须能够通过时间序列视图和周对周的变化追踪随时间的改进。
多次违规
如果经理能够获得最有问题的表格列表或最常失败的检查以优先考虑他们的下一个数据质量倡议,这将非常有帮助。
为了了解数据质量监控解决方案如何为数据领导提供工具示例,请参见图 3-3 和图 3-4。

图 3-3. Anomalo 的 Pulse 仪表板提供组织的数据质量高级统计信息。

图 3-4. 点击任何统计数据可提供数据随时间的趋势,并识别重复出现的表格。在https://oreil.ly/adqm_3_4查看此图的完整版本。
科学家
这些是数据分析师、数据科学家和 ML 平台团队的成员,他们参与构建数据产品和生成见解。他们通常对监控缺失数据、重复数据和分布变化感兴趣。
与工程师不同,这个群体倾向于使用易于使用的用户界面而不是 API。自动化数据质量监控解决方案可以赋予科学家权力的一种方式是为他们提供丰富的可视化工具来探索数据并确定问题的根本原因。
消费者
此类别包括所有依赖工程师和科学家构建的数据产品做出决策的其他人,如产品团队、运营、市场营销和合规性。这些通常是关于收集数据领域的最深的主题专家,并因此在指导数据质量监控和处理问题方面发挥重要作用。
为了建立对数据的信任并避免分散工具的大量使用,监控解决方案应为该组提供关于数据质量的单一真实来源。消费者不太可能参与问题解决,而应通过通知了解可能影响其工作的数据质量问题。这些通知应该清晰、易于理解,并以正确的紧急程度交付。
进行 ROI 分析
在评估所讨论的四个关键因素——您的数据、您的行业、您的数据成熟度和您的利益相关者之后,您可能会决定自动化数据质量监控似乎是个好主意。在这种情况下,您需要通过运行可能的 ROI 评估来说服自己和其他人。这种分析应考虑定量和定性指标。
对于在本章之外进行 ROI 分析的更多细节,有兴趣的读者可能希望查阅案例研究,作者是 Discover Financial Services 的企业数据平台高级总监 Prakash Jaganathan。Discover 的大量数字银行和支付服务产品由数百个软件应用程序支持,并持续产生和存储 petabytes 的数据。该案例研究讲述了为何 Discover 通过订阅机器学习驱动的自动化数据质量监控平台,解决了传统确定性数据质量监控所面临的根本性挑战,以创新和卓越数据质量。
定量测量
要开始 ROI 分析,可以先看看业务中数据质量问题的频率。每个表发生这些问题的频率如何?每个事件通常造成多少成本:包括业务中断、调查和解决时间,以及其他对客户或运营的不利影响?对于你知道的每个数据质量问题,还有多少是未被发现但仍然对你的运营造成了不利影响?
一旦你估计出这个数字,你可以将其乘以每年每个表预期的问题数量,以及需要监控的重要表的数量。如果自动化数据质量监控解决方案的总成本能够减少这些事件的数量和严重程度,以及其产生的成本,那么你就可以证明其是合理的。
此外,看看你的团队在与数据质量相关任务上花费的时间,以及预计通过自动化数据质量监控来减少这些时间。典型任务包括:
-
创建和维护自动化数据检查
-
设置通知和警报
-
调查、探索和根本原因分析
-
长期监控关键指标
如果你有这些任务的历史统计数据,那么你可以计算通过实施自动化数据质量监控预计能够节省的小时数。这些小时可以作为时间和人才投入到其他项目中的回报。最好是能够与供应商进行试验,看看例如你在关心的表上设置监控需要多长时间。如果是内部建设,提前获得清晰的数字可能会有困难,但你可以设定一个目标,使投资变得值得,并在构建概念验证时记住这一点。
在与客户交谈时,我们经常被要求帮助估算配置监控表和分类警报所需的总小时数,以便他们将此时间与今天在数据质量上的支出进行比较。要记住,通过高效的监控平台,大部分数据质量工作将集中在相对较少的重要表上。在一个有 20,000 张表的数据仓库中,我们通常会看到如表格 3-2 中所示的分布:
-
10,000 个表格(50%)根本就不值得监控。通常这些是临时的、中间的或一次性的表格,可能会在未来被删除。
-
9,000 个表格用于处理,并应使用元数据监控数据新鲜度和数据量。我们称之为表格可观察性,它比在整个仓库上运行 ML 模型要便宜得多,同时提供基线水平的数据质量监控。
-
还有 900 个重要的团队特定表格,除了表格可观察性外,业务还希望使用自动化 ML 模型进行深入的数据质量监控。
-
在 90 个关键表格上,他们还希望设置验证规则和指标,以监控一些意外变化。
-
另外还可能有 10 个关键表格,除了所有其他的监控外,还必须具有多个记录级质量验证规则。这些往往是业务上至关重要的事实表。
表 3-2. 数据仓库中的监控表格
| 类型 | 表格 | 占比 | 用途 | 配置 | 监控策略 | 配置每表小时数 | 总配置小时数 | 每表警报频率 | 每周总警报数 | 每警报处理时间(分钟) | 每年处理时间(小时) |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 临时 | 10,000 | 50% | 分阶段、测试或实验中 | 无监控 | 0 | 0 | 从不 | 0 | 0 | 0 | |
| 处理 | 9,000 | 45% | 用于生成重要数据集的生产管道 | 表格可观察性 | 自动检测架构、新鲜度和数据量问题 | 0.01 | 90 | 每年 0.5 次 | 87 | 5 | 375 |
| 重要 | 900 | 5% | 原始数据和团队特定数据集 | 数据质量 | + 自动检测缺失、错误、重复或异常数据 | 0.2 | 180 | 每季度 1 次 | 69 | 20 | 1,200 |
| 关键 | 90 | 0.5% | 驱动数据产品和决策的事实和聚合表 | 数据质量 | + 监控指标和/或段以发现意外变化 | 8 | 720 | 每月 1 次 | 21 | 60 | 1,080 |
| 关键 | 10 | 0.1% | 关键数据元素和执行级别监控 | 数据质量 | + 强制记录级别质量的验证规则 | 40 | 400 | 每周 1 次 | 10 | 60 | 520 |
| 总计 | 20,000 | 100% | 1,390 | 3,175 |
您还应该权衡解决方案的设置和运行成本,如许可证、基础设施和计算。请注意,这些成本的额外考虑因素可能是支出(因此也是您预算)的可预测性如何。
定性措施
自动化数据质量监控的一些定性好处包括:
-
加快开发周期,因为您可以在功能发布后更快地捕捉生产问题。
-
由于高测试覆盖率、更少错误和更快的响应时间,与合作伙伴的信心提高
-
拥有“审计追踪”,您可以记录历史数据检查和数据的过去性能
-
民主化数据质量并提高协作和所有权,从而提高员工的生产力和满意度
-
提升数据的信任度,从而提高其他数据相关工作的投资回报率。
自动化数据质量监控的定性缺点可能包括:
-
对变革的抵制;员工必须掌握新的技能。
-
需要开发新的培训和入职资源。
-
潜在的安全风险;例如,如果您使用的 SaaS 解决方案没有部署在虚拟私有云(VPC)中。
-
(如果您在内部建设)需要随时间维护您的解决方案并承担故障的责任
-
存在假阳性或信息贫乏通知引起的警报疲劳的风险(另一方面,警报可以带有丰富的上下文和可视化,描述问题特征,识别根本原因,并帮助用户了解问题可能的严重性。用户界面还可以提供分类和解决问题的手段。所有这些便利措施在很大程度上有助于减少警报疲劳。)
最终,我们看到数据领导者将提高数据质量的价值视为其整个数据预算(技术和人员)投资回报率的乘数。例如,考虑一个每年在数据技术上花费 3000 万美元,数据专业人员(全面的薪酬)每年花费 7000 万美元的组织。该组织投资这 10000 万美元的预期回报率为 20%。然后,他们每年预期生成的价值为 1.2 亿美元,通过改善人类决策,通过 ML 和 AI 提供更好的运营和更好的客户体验,以及可以直接货币化的新数据产品。
如果数据质量能够显著提高,那么预期价值的增加可能会达到高达 10%。这可能发生在因为减少了追踪数据质量问题而浪费的时间,因此人力投入更具生产力,或者因为决策和机器学习模型的质量更高,直接转化为更高的投资回报率。
最终的效果将意味着该组织将创造价值 1.32 亿美元,每年因更高的数据质量而增加 1,200 万美元的价值。
在实践中,虽然在某些情况下进行严格的投资回报率分析可能是必要的(尤其是为了说服您的财务或采购部门需要投资于数据质量),但我们与许多大型企业合作时,很少有企业会费心进行此类分析。改善数据质量的理由可能是如此明显和强有力,以至于问题更少关于投资回报率,而更多关于速度。
结论
要实现规模化的数据质量监控自动化,您需要进行多项权衡。您需要投资新技术,引入新流程,并承诺解决您发现的新数据质量问题。
我们建立了一个自动化数据质量监控平台,因为我们相信这些权衡对许多公司都是有价值的。沿途中,我们与许多对这一解决方案感到兴奋的企业和团队进行了多次互动。但我们也了解到了时间不合适或者适配不对的情况。在本章中,我们尝试全面阐述为何您可能从自动化数据质量监控中受益,另一方面,它可能不适合您的解决方案。
对于自动化数据质量监控平台的投资回报率感到兴奋吗?在接下来的几章中,我们将提供您所需的详细指导,帮助您迈出下一步。从不同的建模技术和考虑因素到如何提供高质量通知,本书中最技术性的主题即将登场。拿出您的笔记本,特别是您的数据科学笔记本,因为现在是深入实施细节的时候了。
¹ Rishi Bommasani 等人,“基础模型的机遇与风险”,2022 年 7 月 12 日,https://arxiv.org/abs/2108.07258v3。
第四章:使用机器学习自动化数据质量监控
机器学习是一种统计方法,与基于规则的测试和指标监控相比,具有许多优势:可扩展性强,可以检测未知的变化,而且,在将风险人性化的前提下,它还很聪明。它可以从先前的输入中学习,使用上下文信息来减少误报,实际上可以越来越好地理解您的数据。
在前几章中,我们探讨了自动化 ML 何时以及如何对您的数据质量监控策略有意义。现在是探讨核心机制的时候:您如何训练、开发和使用模型来检测数据质量问题,甚至解释其严重性以及发生在数据中的位置。
在本章中,我们将解释哪种机器学习方法最适合数据质量监控,并展示您可以遵循的算法(一系列步骤)来实施这种方法。我们将回答诸如应该采样多少数据以及如何使模型的输出可解释等问题。需要注意的是,遵循这里的步骤不会导致一个准备好监控实际数据的模型。在第五章中,我们将转向调整和测试系统的实际方面,以使其在企业环境中可靠运行。
要求
对于给定问题,有许多 ML 技术可以潜在应用。要找出适合您使用案例的正确方法,需要在前期定义要求至关重要。我们认为用于数据质量监控的模型应具备四个特征:灵敏度、特异性、透明性和可扩展性。
灵敏度
灵敏度是衡量 ML 模型能够检测真正阳性的能力的指标。为了有效,算法应能够在实际表格数据中检测到各种数据质量问题。一个良好的基准是能够检测到影响超过 1%记录的变化。
实际上,我们发现试图检测影响不到 1%记录的变化会导致一个系统产生太多噪音。即使检测到的变化在统计上是显著的,也会有太多这样的变化需要分类和理解,特别是当规模扩展到大量复杂表格时。我们的经验表明,影响超过 1%记录的变化是数据生成或转换过程中的重大结构性变化,可能是重大的新冲击和创伤。
要查找小于 1%的变化,您可以使用确定性方法(如验证规则),或者可以通过在仅查询最重要记录的视图上运行模型来聚焦 ML 在数据子集上。
例如,社交媒体平台可能在单个大事件处理表中跟踪数百种不同类型的事件。在整个表上运行机器学习将捕捉格式和结构最常见的事件类型的严重问题。但如果您想要密切关注每个事件特定子集,您可以选择在每个事件特定的子集上运行模型。
特异性
与灵敏度相对应,特异性告诉您模型在不触发假阳性警报方面的表现有多好。这在数据质量监控中尤为重要,因为警报疲劳可能会威胁整个方法的采纳和功效。
通常,监控系统倾向于因为几个原因而过度报警。一个原因可能是季节性——如果数据中有每天、每周或每年重复的模式,数据看起来可能正在变化,但实际上并没有以异常或意外的方式变化。如果监视器不能聚合受同一数据变化影响的相关列,它也会变得嘈杂。或者如果它对数据的样本或时间窗口评估太小,也可能发送假阳性警报。此外,有些数据集比其他数据集更加“混乱”,因此需要校准每个数据集的检查灵敏度阈值(并可能随时间演变)。
我们将探讨模型如何在第五章中学习和考虑季节性、相关性和其他现实世界数据的挑战。
透明度
当出现问题时,模型应该是透明的,并帮助用户理解和找出问题的根本原因。你可能会认为这与模型本身无关——毕竟,任何复杂的可视化和问题根本原因分析都会在检测到数据问题之后发生。但你的选择确实取决于你使用的机器学习方法。你模型的架构和实现将决定你能够解释和归因其预测的程度。例如,某些机器学习特性可能有助于提高准确性,但在数据质量的背景下解释给用户可能会很困难。
可扩展性
要在数据仓库中每天运行可能涉及数十亿行数据的任务,您的系统必须具备人力、存储和计算成本的可扩展性。它不应该需要管理员进行任何预先配置或重新调整,因为这只会创造另一种手工编写的规则形式,我们已经在第二章中显示这不是一个可扩展的解决方案。它应该对数据仓库的查询占用尽可能小的资源,并且能够在仓库之外的廉价硬件上快速执行。这些约束条件将影响我们建模决策的许多方面,我们将在本章中探讨使解决方案更具可扩展性的方法。
非要求
定义系统不需要做的事情与定义应该做的事情一样有用。你可能还记得第二章中讨论的一个无监督机器学习模型应该是三支柱数据质量方法的一部分,另外还包括基于规则的测试和指标监控。这是因为期望自动化解决所有数据质量问题是不可行的。
下面是我们模型的非要求清单:
-
它不需要识别个别的坏记录(这是基于规则的测试的作用:当需要数据完美时)。相反,我们期望它寻找有意义百分比记录中的结构性变化。
-
并非需要实时处理数据。实时评估数据质量检测的机器学习模型不仅难以扩展,而且可能被迫评估单个记录,这超出了我们的范围。相反,我们期望它能够以每日或每小时批次评估数据。
-
我们不能期望它能够告诉我们数据一直都是损坏的 — 这不是机器学习的工作方式,因为模型必须基于历史数据训练。如果历史数据是错误的,我们无能为力!这就是为什么机器学习方法仅应依赖于识别数据中的新变化。
-
我们不能指望它在没有时间概念的情况下分析数据。模型将会随时间追踪数据以检测变化。如果数据本身没有时间戳,我们将需要开发其他方法来识别数据生成的时间(稍后详述)。
数据质量监控不等同于异常检测。
在我们结束对数据质量监控模型要求的讨论时,值得花一点时间解决一个常见的困惑:异常检测与数据质量监控的区别。
异常检测可以是理解复杂数据集的一种有用方式。有许多方法可以识别异常值,但其中一种最可扩展和灵活的方法是使用一种变体的随机森林,称为孤立森林,来识别远离多变量分布“中心”的数据行,如图 4-1 所示。

图 4-1. 使用 scikit-learn 中的孤立森林(Isolation Forest)查找异常观测的示例(那些在界定的簇外的点);来源于《对玩具数据集上的异常检测算法进行比较》,Scikit-learn。
通过机器学习可以实现异常检测,它旨在发现数据的不寻常方面。但与数据质量监控的相似之处就到此为止。毕竟,每个数据集都会有异常观察结果——即使正态分布也会有极端值!这些异常值可能很有趣(它们可能是欺诈记录或者仅仅是非常罕见的事件或数据组合),但它们未必会是数据质量问题,这可能会影响常见或罕见记录的概率是一样的。
要识别数据质量问题,我们需要知道数据到达表中的分布是否出现了突然的结构变化。我们需要知道过去记录是否总是以某种分布、模式或关系出现,而现在突然之间,这种情况以显著的方式发生了变化。另一方面,每个数据集都有异常值。异常检测解决的是一个根本不同的问题。
机器学习方法和算法
现在我们已经涵盖了需求,我们将分享我们推荐的方法以及您可以采用的步骤来实施它。我们不愿声称这是使用机器学习检测数据质量问题的唯一方法,但我们尚未遇到比实践中更有效地满足要求的方法。正如常言道,细节决定成败。诸如特征工程和参数调整/阻尼在实现有效的实施与在真实世界数据上过度或不足报警之间起着至关重要的作用,我们将在第五章进一步讨论。
请回忆,我们希望开发一个机器学习模型来检测数据中的意外变化,而无需任何人员标记数据并告诉我们什么构成了数据质量问题。这使得这类机器学习问题成为无监督学习任务。然而,数据中确实有一个我们可以像人类标签一样使用的特征,那就是数据到达表中的时间。
这就是这种方法的关键洞察力所在。每天,我们都会对数据进行快照。然后,每天,我们都试图训练一个分类器来预测数据是否来自今天。

如果今天的数据在统计上没有什么显著的特点,那么我们尝试训练分类器的努力将会失败——预测数据是否来自今天应该是一个不可能的任务,基本上是扔硬币!
另一方面,如果我们能够构建一个分类器,能够相当准确地预测数据是否来自今天,那么我们可以非常确信今天的数据有些不同寻常。而且这种不寻常是有意义的——因为几条记录中的少量随机变化是不足以训练模型做出预测的。事实上,我们甚至能够使用这种方法来说出变化的程度,并设置适当的阈值以避免警报过度疲劳。通过解释模型的预测,我们可以解释数据内部最有可能发生的情况。
即使变化并不有趣,模型也能检测到显著的变化。最明显的例子是日期列。该列每天都会变化,因此它总是代表数据的显著变化!我们将在第五章讨论如何处理这类情况。另一种可能不具有意义的变化是最终用户根本不关心的变化。我们将讨论如何在第六章处理这类警报。
现在你已经了解了主要思路,让我们详细探讨每一步:
数据抽样
如何构建用于训练模型的数据集,以及合适的样本大小是多少?
特征编码
如何从表中的一行转换为模型可以用来进行预测的特征集?
模型开发
为这种算法选择正确的模型架构,以及如何训练模型?
模型可解释性
一旦你训练好一个模型,如何用它来解释数据质量问题?
数据抽样
构建任何模型的起点是从总体数据池中抽样创建一个训练数据集。对于我们刚刚描述的算法,您需要从“今天”(标签为 1 表示我们试图预测的类)和“不是今天”(标签为 0)中随机抽取一组健壮的数据。 “不是今天”的数据应该是之前的时间比较周期的混合物:昨天(或上次获得数据更新的时间)用于突然变化,以及其他周或年的其他时间用于控制季节性(参见章节“季节性”)。
例如,在图 4-2 中,我们看到一个示例数据集,每天的数据量在 15 万到 25 万行之间。一个健壮的样本可能包括来自以下日期的 1 万条记录:
-
2021-01-16:您希望评估数据质量问题的日期
-
2021-01-15:昨天,有助于识别任何突然变化
-
2021-01-09:一周前,为了控制星期几季节性因素
-
2021-01-02:两周前,以防上周出现异常

图 4-2. 展示样本大小与数据集整体大小的对比图。
样本大小
在实践中,我们发现这种算法每天至少需要 100 条记录才能有机会在相对复杂的数据中找到有意义的变化。但这引出了一个问题——对于算法来说,记录数的上限是多少才是有效的?
可以选择抽样率来平衡计算成本与精度。我们已经针对每天新增数十亿行的数据集运行了这种算法。在实践中,并基于严格的测试,我们发现每天抽样 10,000 条记录(如果随机抽样)提供了足够的数据来捕获大多数数据质量问题,即使这些问题只影响 1–5% 的记录。随着样本量超过 100,000,质量改善逐渐减弱。
可以使用大样本量(比如,每天 1,000,000 条记录),但计算成本尚未证明其价值。数据集需要非常稳定(背景混乱较少),变化必须在非常小的记录百分比内(比如,0.1% 的记录)才能使增加抽样大小变得值得。
将抽样固定为一个固定的样本大小(10,000 条记录)似乎是一个错误,而不是抽样,比如,数据的 10%。毕竟,如果我有 10 亿条记录,10,000 条如何代表那么庞大的人口?
或许出乎意料的是,因为样本完全是随机选择的,其精度并不依赖于数据的总大小,而只依赖于绝对样本大小。例如,考虑估计一个国家的平均收入。仅因为中国人口为 14 亿,卢森堡人口为 60 万,这是否意味着我们需要在中国抽样更多的人来估计平均收入?不是的。在这两种情况下,我们可以抽样 1,000 人,并得到一个非常好的平均收入估计。
偏差和效率
很重要的一点是从表中随机抽样样本。如果抽样中存在任何偏差,算法将能够发现这种偏差,并将其表示为数据中的虚假正变化,这会使用户感到困惑。
确保抽样尽可能高效也至关重要。在实践中,从数据仓库中随机抽取记录对于机器学习模型通常是这类系统中最昂贵的操作。这是因为表中可能包含数十亿甚至数万亿的记录,以及数百或数千列。如果一个查询天真地要求将每条记录读入内存或通过网络发送以进行抽样,这将对性能造成灾难性影响并产生大量的数据仓库成本。
偏倚和效率有时可能存在相互制衡的关系。例如,在现代数据仓库中有效地扩展随机采样的一种方式是使用 TABLESAMPLE 操作符,而不是 random() 调用。TABLESAMPLE 操作符是以一种允许仓库在查询执行期间有效地对随机记录进行采样的方式实现的,而无需将记录读入内存——但在某些情况下,它可能会对偏倚产生负面的权衡。
在 BigQuery 中,TABLESAMPLE 操作符的实现是通过“随机选择表中一定百分比的数据块,并读取所选块中的所有行”来工作的。文档继续解释说,通常情况下,“如果 BigQuery 将表或表分区分割成大约 1 GB 的块,则...” 这意味着,在实践中,TABLESAMPLE 操作符返回的结果通常在 BigQuery 中不会是随机的,而可能完全在一个分区中。如果您对标识符(例如客户 ID)进行了数据分区,并且经常用于连接,则将具有特定子集的客户远比其他人更有可能出现在您的随机样本中。这可能会显著偏倚您的 ML 结果,导致您随着时间的推移不断看到用户群体的变化,而这完全是由于抽样实现而不是数据本身的任何真实漂移所导致的。
那么,如何高效抽样并避免偏倚呢?以下是我们的建议:
-
确保每次运行算法时仅使用少量天数的数据。这些天数可以存储为快照,因此无需再次查询它们(尽管重新查询它们可能是值得的,因为表中的历史数据可能已更改)。
-
确保表格在您用于选择数据的日期列上进行了分区。这允许数据仓库有效地导航到仅代表这些日期的磁盘文件,并读取和处理仅有的这些数据日期,而无需访问其他无关的日期。
-
使用
TABLESAMPLE操作符可以有效地对比所需的较大的近似随机样本进行采样(例如,如果您需要 0.3%,则采样 1%)。通常情况下,可以使用该操作符进行采样的最低百分比是 1%,尽管实现因仓库而异。请注意,并非所有数据库或数据仓库都以健壮的方式支持TABLESAMPLE——请参阅前文有关 BigQuery 的段落。 -
统计您在查询日期上将拥有的总记录数,以便了解您需要查询的确切样本百分比。
-
使用类似以下代码获取最终随机样本:
random() <= X,其中X可以给出TABLESAMPLE操作后每个日期大约正确行数的近似值。 这比看起来像order by random() limit 10,000的方法更有效,后者需要在仓库的主节点中将所有数据加载到内存中,并按随机数进行排序,然后应用限制。random() <= X方法的好处是可以在仓库中的每个工作节点上以分布式方式应用。 请注意,其轻微缺点是您的随机样本不太可能恰好是 10,000 行,而是会接近某个数。
查询数据时的另一个重要考虑因素是确保 WHERE SQL 过滤器的高效实施。 例如,对于具有日期列 created_date(以 YYYY-MM-DD 格式指定为字符串)的表,这样做非常低效:
WHERE cast(created_date as date) = cast('2023-06-01' as date)
此代码需要数据库在内存中读取每个分区,并转换 created_date 列以决定是否应包含记录。
而是,请尝试:
WHERE created_date = '2023-06-01'
现在,数据仓库可以使用关于每个分区的元数据来决定从查询中完全排除哪些分区。 对于格式化有不寻常日期或时间分区的表格,这可能非常具有挑战性。 在 Anomalo,我们不得不为 图 4-3 中的所有类型添加支持。

图 4-3. 日期/时间分区类型示例。
有时候,杰里米开玩笑说我们很快将支持“自凯文·培根诞生以来的天数”格式的时间。
特征编码
ML 模型通常不是在原始数据上训练的,而是使用数值特征进行学习,这些特征是将原始数据转换为模型可以使用的信号。 如何转换原始数据对模型性能有重要影响,通常需要 ML 和数据领域专业知识。 这个过程称为特征工程,在我们的异常检测算法中必须完全自动化。
这是它的工作原理:样本中的每条记录都有多列,每列可以是整数、浮点数、字符串、布尔值、日期或时间戳,或者像 JSON 或数组这样的复杂类型。 您需要一个自动化过程,遍历每一列(必要时展开复杂类型,如 JSON 为子列——详见 “半结构化数据” 以获取更多信息),提取可能对模型有趣的信息,并将此信息编码为 ML 特征的浮点数矩阵。

图 4-4. 将数据编码为特征。请注意,响应变量(又名标签)对应于日期:昨天为 0,今天为 1。在https://oreil.ly/adqm_4_4上查看此图的完整版本。
您需要开发一组候选编码器类型,以应用于您认为可以告诉您数据是否以有意义的方式发生变化的特征(见图 4-4)。以下是我们推荐的一些编码器:
Numeric
将布尔值、整数和浮点值转换为浮点数
Frequency
样本数据中每个值出现的频率
IsNull
用于判断列是否为 NULL 的二进制指示器
TimeDelta
记录创建与时间之间的秒数
SecondOfDay
记录创建的时间点
OneHot
一种独热编码器,允许你将特征值(如类别或频繁整数值)映射到列中每个唯一值的二进制是或否指示变量
数据科学家可能会关心常见编码器如词项频率-逆文档频率(TF-IDF)、均值编码或拉普拉斯平滑的适用性。许多标准编码器对于基于树的模型(对数转换、均值编码、主成分分析[PCA])并不十分相关。其他编码器可能需要大量关于具体数据的专业知识才能很好地使用(拉普拉斯平滑),还有一些可能是有用的,但解释起来非常困难(TF-IDF、词/向量嵌入)。
您必须小心您的编码器设计得多复杂,因为最终,您将需要使用这些编码器来向用户解释数据质量问题。例如,我们测试了一个用于时间、整数和数值字段的“间隔”编码器,它将每个观察值与该列中下一个较大值之间的间隔进行计算。在实践中,这能够检测到某些数据质量问题,但它也会检测到许多其他数据的变化,这些变化对于我们的目的来说既难以理解又/或不相关,例如数据记录方式的粒度变化或观察值的密度无关的变化。
模型开发
为了满足可伸缩性要求并在实际环境中工作,您需要一个快速推断和训练的模型架构,可以在相对小的样本上进行训练,并且将泛化到任何类型的表格数据(在适当的特征编码下)。梯度增强决策树非常适合这种用例,您会发现像XGBoost这样的库非常适合模型开发。
梯度提升决策树通过在数据集上构建一系列决策树(或“步骤”)的迭代方式工作,其中每棵树都旨在纠正之前所有树的错误。最终,模型的预测考虑了在每个步骤训练的所有树的结果(这被称为集成模型)。参见图 4-5。

图 4-5. 梯度提升决策树(改编自邓浩文等人,“集成学习早期预测基因特征新生儿黄疸”,BMC 医学信息学和决策制定 21 卷 338 号[2021 年])。
值得注意的是,梯度提升决策树仅有少量的参数对调整非常重要(主要是学习率和每棵树的复杂度,尽管还有其他因素),并且可以在包含数千甚至数百万条记录的数据集上快速训练。
一些替代方法,比如线性模型,过于简单,无法学习大多数结构化数据集中的复杂模式。其他方法,如神经网络,通常对于这类问题过于复杂,并且需要极大量的异构数据才能发挥出很强的效力(比如在图像和语言模型中)。
与任何结构化机器学习技术一样,梯度提升决策树的缺点是需要进行特征工程:人类专家必须告诉模型在进行预测时应该考虑数据的哪些方面,这可能需要大量时间和精力。
训练与评估
理论上,梯度提升决策树可以无限迭代下去,因此非常重要的是设定步数的上限。为了做到这一点,通常需要在每一步之后评估模型的性能。选择数据的随机部分作为保留集用于评估(而非训练),并在每次迭代后测试模型。您的模型性能将表明今天的数据是否存在异常。
具体而言,在实践中我们通常看到三种模型性能模式,如图 4-6 所示。在这些图表中,x 轴表示添加到模型中的树的数量(迭代次数),而 y 轴则绘制了模型准确性的一种度量(损失函数的对数)。请注意,这里 y 轴技术上是绘制模型预测中的“错误”量,因此较低的值表示更高的准确性。
第一种情况,“无异常”,是指在训练数据上几乎没有进展,而测试数据的表现很快变得更糟。这意味着新数据中不太可能存在任何异常。
第二种情况,“不完整”,发生在模型没有足够时间收敛时。您达到了树的最大数量(设置为防止模型无限运行),但仍然发现训练误差和测试误差在下降。您需要增加更多的树,或者更谨慎地增加学习率,这会导致梯度提升算法在评估每棵树时采取更大的“步骤”。
第三种情况,“最优”,发生在模型在训练和测试上取得良好进展,直到测试损失开始增加的某一点。这表明您可以在测试损失达到最小值时停止。在那时,模型将尽可能多地了解区分这两个数据集的内容,考虑到学习算法的其他参数。

图 4-6。当树的数量增加时,绘制模型在训练和测试数据上的表现时遇到的三种最常见情景。使用对数损失函数来衡量性能(y 轴上较低的值表示更好的性能)。
在实践中,为了提供一致可解释的模型统计和可解释性结果,您需要在优化单一数据集的模型和构建能够泛化到不同时间段多个数据集的模型之间取得平衡。
计算效率
许多组织拥有重要的数据表,可能包含数十亿条记录。例如:
-
来自金融服务行业的交易数据
-
来自高流量应用程序或网站的原始事件数据
-
数字广告印象和事件级数据
-
物理传感器数据
-
社交平台的消息信息
在这种规模的数据情况下,很容易创建一个监控策略,这可能会成本过高,或者简单地无法成功运行,即使使用现代数据仓库也是如此。
因为我们对每天采样的记录数量设定了限制,模型中的大部分计算和内存使用量将随着增加的列数呈线性增长。例如,在扩展决策树的每个节点时搜索最佳分割点将随着需要搜索的列数线性增加。尽管典型表格通常有 10 至 50 列,但表格通常会有 200 列,有些表格甚至有数千列。此外,表格可能包含 JSON 数据,您需要自动展开为新的合成列,在某些情况下可能会导致表格拥有 10,000 列。
下列优化措施可以使您的算法更具计算效率:
-
确保每次只查询一天的数据,并尽可能快照结果以建立历史。请注意,这将带来成本,因为算法在第一天将有更少的历史数据可供使用,并且在“冷启动”场景中不会像在其他情况下那样有效。
-
使用数据仓库从表格中随机抽样记录(使用之前提到的有效技术在“偏差和效率”中),并在随机样本上计算更复杂的分析或机器学习结果。
-
如果使用梯度提升决策树,请限制深度和总树数,因为我们通常不寻求非常复杂的交互作用,并在训练过程中如果测试误差显著增加则提前停止。
-
优化学习过程本身,这可能包括使用稀疏编码、通过多进程分布学习或利用 GPU 等步骤,具体取决于您的计算平台和学习算法。
模型可解释性
如果您的模型在测试集上表现良好,这表明您可能发现了潜在的数据质量问题。下一步是解释模型发现了什么。
可解释性是关键,因为它告诉您今天的数据异常程度。这使您可以执行各种调整以避免警报疲劳(更多详情请参见第五章和第六章)。对于那些确实发出警报的问题,了解严重程度将有助于最终用户优先处理其响应。
其次,可解释性告诉您数据中异常发生的位置。这使您可以将调查员指向数据的正确部分,并创建各种有趣的根本原因分析辅助工具,例如坏数据样本(更多细节请参见第六章)。
如何解释模型可解释性?其核心思想是衍生一个分数,以表明数据集中每个个体{行,列}单元对模型预测的贡献。虽然有多种方法,我们使用的是SHAP,其本质上是对数据集中每个单元进行局部线性估计来近似算法的工作方式。
要了解这在实践中如何运作,假设我们试图检测信用卡交易数据表中的数据质量问题,并从昨天和今天中抽取了 10,000 条记录,对我们的特征进行编码,并建立了预测每条记录到达的哪一天的模型。然后让我们通过 SHAP 解释过程跟随以下四条记录:
| 金额 | 类型 | FICO 评分 | 品牌 | 类型 | 信用额度 | 来源 | |
|---|---|---|---|---|---|---|---|
| $18 | 刷卡 | 684 | 发现 | 借记 | $12,564 | 今天 | ||||||
| $59 | 芯片 | 578 | 万事达卡 | 信用 | $7,600 | 今天 | ||||||
| –$445 | 芯片 | 689 | Visa | 信用 | $6,700 | 昨天 | ||||||
| $137 | 芯片 | 734 | 万事达卡 | 信用 | $7,100 | 昨天 |
在这种情况下,我们有两条来自昨天和两条来自今天的记录。(回想一下,源列并不用于预测数据到达的日期;相反,它是我们训练模型预测的响应。)
假设我们拿出模型,并为每一行做出预测,我们认为它可能在哪一天到达:
| 金额 | 类型 | FICO 评分 | 品牌 | 类型 | 信用额度 | 来源 | 预测的 Pr( 今天 ) | |
|---|---|---|---|---|---|---|---|---|
| $18 | 刷卡 | 684 | 发现 | 借记 | $12,564 | 今天 | 51% | ||||||
| $59 | 芯片 | 578 | 万事达卡 | 信用 | $7,600 | 今天 | 78% | ||||||
| –$445 | 芯片 | 689 | Visa | 信用 | $6,700 | 昨天 | 45% | ||||||
| $137 | 芯片 | 734 | 万事达卡 | 信用 | $7,100 | 昨天 | 52% |
在这种情况下,我们发现我们的模型认为第二条记录是今天的概率为 78%,而其他三条记录的预测都在 50% 的平均预测值的 ±5% 范围内,这表明模型对数据来自哪一天没有明显的偏见。
与直接使用预测概率(由于概率自然地限制在 0% 到 100% 之间,很难表达为线性关系),我们将概率转换为它们的对数几率,使用公式 对数几率 = ln [ 概率 / (1 - 概率) ]:
| 金额 | 类型 | FICO 评分 | 品牌 | 类型 | 信用额度 | 来源 | 预测的 Pr( 今天 ) | 对数几率 | |
|---|---|---|---|---|---|---|---|---|---|
| $18 | 刷卡 | 684 | 发现 | 借记 | $12,564 | 今天 | 51% | 0.02 | ||||||
| $59 | 芯片 | 578 | 万事达卡 | 信用 | $7,600 | 今天 | 78% | 0.55 | ||||||
| –$445 | 芯片 | 689 | Visa | 信用 | $6,700 | 昨天 | 45% | –0.09 | ||||||
| $137 | 芯片 | 734 | 万事达卡 | 信用 | $7,100 | 昨天 | 52% | 0.03 |
之后,我们可以运行 SHAP 算法,将这些对数几率统计分解为每个列的贡献的线性组合,如在 ML 模型中使用的那样(实际上,我们需要在特征级别获取 SHAP 值,然后聚合这些值,但你明白我的意思):
| 金额 | 类型 | FICO 分数 | 品牌 | 类型 | 信用额度 | 预测概率(今天) | 预测概率(今天) | 对数几率 | |
|---|---|---|---|---|---|---|---|---|---|
| 0.01 | 0.02 | 0.02 | –0.01 | 0.00 | –0.01 | 今天 | 51% | 0.02 | |
| –0.03 | 0.01 | 0.41 | 0.19 | –0.01 | –0.03 | 今天 | 78% | 0.55 | |
| 0.02 | –0.03 | –0.05 | 0.02 | –0.03 | –0.02 | 昨天 | 45% | –0.09 | |
| 0.01 | –0.02 | –0.01 | 0.01 | 0.02 | 0.02 | 昨天 | 52% | 0.03 |
在这种情况下,我们发现 FICO SCORE 和 BRAND 列的值对于模型预测第二条记录来自今天有显著贡献。查看上述数据值,我们可以看到这对应于:
-
FICO SCORE = 578 -
BRAND = 'Mastercard'
这表明,在 Mastercard 交易的低信用分布中可能发生了异常情况(尽管在这里我们只检查了几条记录—实际上,我们将查看每天所有 10,000 条记录的 SHAP 值分布)。
在对 SHAP 值进行归一化和适当调整之后(如第 5 章中的技术),最终结果就是我们所称的“异常分数”。重要的是,这个分数可以聚合和/或切片,以提供多种不同粒度的细节。
在最低层次上,您可以查看采样数据中每个个体{行,列}单元格的异常分数。从这里,您可以对一行的异常分数进行聚合,找出最异常的条目,或者按行集合找到异常段落。您可以按列计算平均异常分数,找出最异常的列。或者您可以计算整个表的异常分数。您还可以对异常分数进行聚类,以找出跨列的相关性(有关详细信息,请参见第 5 章)。
知道异常分数对于数据发生重大变化的情况至关重要。通过计算表中每条记录的分数,您可以创建将异常放入背景的可视化,如图 4-7 所示。

在这个样本商户数据集中,数据质量监控平台检测到一个问题:在merchantcategorycode列中,值为fastfood的数据显著减少。与该表中其他值的异常分数相比,这个异常分数是可以看到food值同时显著增加。这两个变化可能相关,因为fastfood记录突然被错误分类为简单的food。请在https://oreil.ly/adqm_4_7上查看这幅图片的完整版本。
如您在 Figure 4-7 中所见,您可以为异常分数分配人类可读的类别,以帮助解释。根据我们处理各种数据集的经验,我们将异常分数分为六个不同的桶,从最小到极端。这些类别基于整体异常分数的对数——每两个桶代表分数增加一个数量级:
Minimal
数据几乎没有显著变化。
Weak
一小部分数据受到需要解释和仔细研究以检测的变化的影响。
Moderate
数据的一小部分受到明显变化的影响,或者受到需要简单解释的变化的中等百分比影响。
Strong
数据的一大部分受到明显变化的影响,或者大多数数据受到容易解释的变化的影响(尽管一开始可能不明显)。
Severe
大多数数据受到明显变化的影响。
Extreme
今天的数据明显受到影响的变化。
您可能注意到 Figure 4-7 中的一个阈值——使用每个表的异常分数来学习何时触发警报的自定义阈值非常重要,因为某些表中的数据变化比其他表频繁。我们将在 Chapter 5 讨论这一点。
用伪代码综合一下
下面的 Python 伪代码示例说明了如何应用本章描述的方法来找到两天数据之间的异常,并按列汇总它们。但不要太过字面地理解这段代码;它只是简单地说明了概念及其高层次的整合方式。特别地,请注意,它忽略了更复杂的问题,如季节性、多个回溯和相关特征,并且没有详细实现抽样、特征工程或异常分数计算部分。
# General imports
import pandas as pd
import datetime as dt
import xgboost as xgb
from sklearn.model_selection import train_test_split
from shap import TreeExplainer
# Import hypothetical sub-modules that perform more detailed tasks
from data_access import query_random_sample
from feature_engineering import determine_features, encode_feature
from explainability import compute_column_scores
def detect_anomalies(
table: str,
time_column: str,
current_date: dt.date,
prior_date: dt.date,
sample_size: int
) -> dict[str, float]:
这里我们定义了一个伪代码中的方法,通过比较两个不同日期的样本,训练模型并计算异常分数来检测数据中的异常。
它接受以下参数:
table
用来查询表的名称
time_column
用于过滤数据的时间列的名称
current_date
用于采样数据的当前日期
prior_date
用于采样数据的先前日期
sample_size
每个日期随机抽样的行数
它返回一个字典,其中每个键是列名,每个值是该列的异常分数。
伪代码的下一部分实现了方法的主体,并将我们从数据抽样步骤一直到解释模型预测的过程:
# Obtain random samples of data for the specified dates
data_current = query_random_sample(
table, time_column, current_date, sample_size)
data_prior = query_random_sample(
table, time_column, prior_date, sample_size)
# Create a binary response variable indicating the date
y = [1] * len(data_current) + [0] * len(data_prior)
# Concatenate the data, ensuring the order of concatenation
data_all = pd.concat([data_current, data_prior], ignore_index=True)
# Determine the features to build based on the data columns
feature_list = {
column: determine_features(data_all, column)
for column in data_all.columns
}
# Encode the features, here assuming that encode_feature returns a DataFrame
encoded_features = [
encode_feature(data_all, column, feature)
for column, feature in feature_list
]
# Combine the encoded features into a single DataFrame
X = pd.concat(encoded_features, axis=1)
# Split data into training and evaluation sets
X_train, X_eval, y_train, y_eval = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Train a machine learning model using the features and response variable
model = xgb.XGBClassifier()
model.fit(
X_train,
y_train,
early_stopping_rounds=10,
eval_set=[(X_eval, y_eval)],
verbose=False,
)
# Obtain SHAP values to explain the model's predictions
explainer = TreeExplainer(model)
shap_values = explainer.shap_values(X)
# Compute anomaly scores for each column based on the SHAP values
column_scores = compute_column_scores(shap_values, feature_list)
return column_scores
其他应用
我们专注于无监督机器学习如何帮助您在数据持续变化的情况下检测突发的结构性变化。然而,本章中概述的机器学习方法还有两个值得一提的用例。
第一个是发现传统数据质量问题,这些问题将出现在您数据历史中的震荡和疤痕中。可以通过在历史日期序列上运行本章概述的算法并调查发现的异常来完成此操作。事实上,在第五章中,我们将概述我们如何使用这一过程(我们称之为回测)来衡量我们的模型的有效性。
但请注意,这种方法可能会带来一些复杂性。首先是您可能会发现非常难以解释的问题。组织中经常会发生没有人记得的变更,验证这些变更是否令人担忧将需要昂贵且繁琐的调查工作。第二个复杂性是,您可能期望找到一些根本不存在的问题。当已知的数据质量问题得到修复并且团队补充数据以修复缺陷后,您就不应该再在数据历史记录中检测到该问题。
第二个用例更为重要,我们将在这里简要提及。与其使用无监督机器学习来比较同一表中不同时间的数据,您可以比较同一表中(或具有相同列模式的不同表中)的两个数据样本,以找到它们之间的有意义差异。
在这种情况下,无监督机器学习算法将检测并帮助解释两组数据之间的任何显著分布或关系差异。由于使用了抽样,这种方法可以应用于庞大的表格,甚至是位于不同源仓库或数据库中的表格!
这允许进行以下类型的应用程序:
-
将源数据库中的原始数据与目标数据仓库中的清洗和转换数据进行比较
-
比较当前 ETL 流水线版本的数据与新提议版本生成的数据
-
将当前数据样本与遥远过去的样本进行比较
-
比较来自不同业务部门、地理位置、产品类别或营销活动的数据
图 4-8 展示了监控平台如何将此功能呈现为用户可以配置并按需运行的自定义检查,以比较和对比感兴趣的数据集。
结论
无论您是经验丰富的数据科学家还是新手机器学习者,我们希望本章对构建模型以检测数据分布在一天之内的突变变得更加有用。我们已经涵盖了整体概念,该概念依赖于尝试构建分类器,以预测表中给定行是否来自今天的数据。如果您能够做到这一点,显然今天的数据发生了明显的变化。您可以使用 SHAP 值为表中的个别行打分,以表明它们在多大程度上帮助模型做出决策。对于数据质量监控而言,这些分数可以成为数据异常性的指标,以及异常的方式。这种方法甚至可以扩展到解释数据的历史变化或比较两个 SQL 查询结果的分布。

图 4-8. 使用无监督机器学习,数据质量监控平台可以揭示一项检查,允许用户比较两个数据集。
我们刚刚描述的步骤在实践中可能听起来很简单,但一旦涉及到处理真实数据的细节,一切都会发生变化。真实数据具有季节性趋势,包含不希望将其视为独立问题的相关性,并且经常在原地更新而没有任何指示——这仅仅是其中的一些障碍。我们将讨论这些挑战,以及您如何克服它们,在第五章中。
第五章:建立适用于现实世界数据的模型
在第四章中,我们分享了一个利用无监督机器学习进行数据质量监控的算法。阅读这些步骤和在任意实际世界数据集上实际构建表现良好模型是两回事。如果您没有考虑到季节性、基于时间的特征和列之间的相关性等细微差别的策略,您的模型可能会过度或不足报警,通常是非常显著的。
除了了解需要注意的陷阱外,您还需要持续评估模型与基准数据的对比情况,以找出改进的位置和方式。我们将分享有效模型测试的方法,包括开发一个库以将完全良好的数据引入混乱(伴有邪恶笑声)的思考。
数据挑战与缓解
要使您的模型真正有价值而不是嘈杂,您需要采取策略来克服野外数据所带来的挑战。
季节性
人类是非常季节性的生物。我们的行为模式会随着一天中的时间和一周中的日期而改变。我们每个月大致在同一天支付账单,并且每年大约在同一时间度假。大多数数据在某种程度上反映了人类的行为或受人类行为的影响,因此这些季节性模式几乎出现在我们关心的所有数据中。
正如你可能会回忆起的,我们的方法依赖于比较今天的数据和昨天的数据,具体可以参见第四章。但由于季节性的影响,事实证明这并不足够。例如,今天是星期一,昨天是星期天,数据的许多差异是由于季节性而非数据质量引起的问题。
如果改为始终将今天的数据与前一周的同一天的数据进行比较(例如,如果今天是星期一,则查看上周的星期一数据)呢?不幸的是,这并不能避免所有潜在的问题。首先,如果您的策略仅检查上周的数据,您将不知道问题存在了多长时间——它可能在过去的整个上周存在,或者只是今天才出现。其次,如果上周一存在数据质量问题呢?如果今天的数据是正常的,它可能看起来异常,只是因为它与上周一发生的情况不同。第三,如果上周一是假期,那么那一天的一切都可能异常。
要控制这些因素,有必要从过去多个不同时间点(昨天、前天、一周前、两周前等)采样数据。如果今天的数据与任何这些之前的日期比较时看起来“正常”,那么今天的数据就不应该异常。
另一种对抗季节性的方法是每次监控数据时自动生成大量的元数据统计信息。然后,您可以在时间上使用时间序列模型来识别特征是否具有长期一致的季节性趋势,并抑制这些特征。
时间特征
在您将天真的 ML 算法部署到现实世界后,您几乎肯定会遇到的问题是:表格中通常至少有一列与时间直接相关,例如时间戳或 ID。查看这些列并知道数据是否来自今天非常简单!在这些时间相关特征吸引过多模型注意力之前,我们需要识别并完全从样本数据集中删除它们。
我们的时间戳特征工程会计算每个时间戳与用于按时间分区数据的列之间的差值,因此通常会消除“我有 10 个不同的时间戳,它们都与时间相关”的明显相关性。难以处理的是那些不那么明显的情况。我们常遇到的示例包括:
-
自增 ID(每个新客户都获得稍大的 ID,因此您可以始终识别“今天”的记录为那些具有更大客户 ID 的记录)
-
表示日期信息的字符串或整数,如“月中的一天”或“星期中的一天”,这些信息总是在变化
-
应用程序或日志语义的版本标识符可能会不规律或频繁地更改,这取决于系统更新频率。
通过简单的汇总统计信息,例如检查某个特征是否每天都比前一天大,可以识别出其中一些问题。但在实际操作中,通过使用完整数据集构建一个额外简单版本的模型,您可以获得更健壮的覆盖范围。只需查找在很长时间内对该模型的预测非常重要的任何特征¹,然后将其从真实模型的数据集中删除。
混乱的表格
由于多种原因,数据集可能非常混乱。可能会有人类根据不可预测的时间表执行特定过程(如营销活动),这些过程会显著影响数据。或者,生成数据的产品或服务可能还处于成熟阶段,并且由敏捷工程团队快速更改中。如果不考虑表格的混乱程度,您的模型会平等对待所有数据,并在混乱表格上发出过多警报,而在更稳定的表格上发出过少警报。(在第六章我们将更详细地讨论警报。)

图 5-1. 随时间变化的表格异常分数和学习阈值示例。
因此,通过建立 ML 模型检测到的变化严重性的时间序列,设置通知阈值非常重要。图 5-1 给出了一个示例,其中表的整体异常分数(对数尺度上)基于 SHAP 值的平均幅度。这让您可以使用时间序列模型来学习每个表的混乱程度,并建议一个合理的警报阈值,可以随时间动态上下移动。
在模型首次开始观察表中数据时,为了避免噪音,我们建议从一个非常保守的阈值开始,并逐渐将其降低到数据集中存在的混乱水平。您可以从一个非常非常高的阈值开始(以至于模型几乎不可能在初始运行时触发警报),然后指数衰减基准阈值,使其向零逼近;一个合理的方法是每隔约 10 天衰减一次,衰减因子为二。然后,您可以将该基准阈值与适合您记录的分数的时间序列模型混合使用。
就地更新表
在第四章中,我们指出,我们的算法不应该在没有时间概念的情况下做出决策。由于某些类型的表格如何更新,这在实践中可能会非常棘手。
您可能在数据仓库中使用几种不同类型的表格:
静态表
这些是没有时间列的表格。它们可以是维度表或查找表(例如,关于特定实体已知的所有人口统计信息),也可以是汇总表(例如,关于一组实体当前状态的一组汇总统计信息)。
对于这些表,您需要每天对数据进行快照,因为任何记录都可能在任何时间更新(或整个表可能被删除并替换)。
日志表
这些是仅在现有表格中添加新记录时发生的唯一更改的表格。旧记录永远不会发生任何更改。这通常是原始交易或事件级数据的情况。
这些表通常有一个created_at时间列,指示每条记录的创建时间,并且可以用于将数据分割成基于时间的样本。
就地更新(变异)表格
这些是乍看之下似乎是日志表格的表格,因为每条记录对应特定事件或交易,并且新记录定期添加到表中。然而,这些记录本身在初始写入后可以更改。例如,电子商务订单表可能起初没有具有订单日期的记录,但尚不知道运输日期 —— 它从 NULL 开始,并在未来几天内填写一旦设置了运输日期。
这些表通常具有created_at时间列,但它们还将具有updated_at时间列,用于跟踪每条记录的最后更新时间。您需要小心处理这些表。
检测表中记录是否经常更新就地的一种方法是跟踪度量指标的历史值随时间的变化。例如,图 5-2 记录了每天表中记录的数量。x 轴是表中的时间列(datecreated列),而 y 轴是日期。每天,您可以比较当天获取的行数与前一天的情况。在图 5-2 中,方块的颜色基于数据的变化情况及其程度。

图 5-2. 表的时间变化中行数的变化。查看此图的全尺寸版本 https://oreil.ly/adqm_5_2。
例如,对于 2023-06-09(根据datecreated),当我们首次观察到该日期的记录时,我们发现只有 498 行。但我们在第二天检查时(2023-06-10),发现有 514 行。这表明在随后的日期添加了更多的记录。
我们通常在这个可视化中观察到两种模式:
-
有彩色对角线模式意味着表中频繁更新新数据。具体而言,新数据在出现后的几天内更新。对角线的宽度表示您需要等待数据在表中“成熟”的时间。在图 5-2 中,我们看到一个对角线,表明成熟大约需要一天的时间。
-
一条水平线表示,在给定日期运行了一个批处理过程,该过程更改了大量历史数据——通常是为了解决数据质量问题或迁移数据集。
还有第三种类型的模式,即竖直变化线,但这种情况要少得多,因为它会表明有一个特定的日期,数据频繁更改。有关所有三种模式的视觉示例,请参见图 5-3。

图 5-3. 使用颜色跟踪数据随时间变化的更新就地表中的可视模式及其含义。
更新就地的表存在的问题是它们似乎总是在最近的日期上出现异常。例如,具有空运输日期的订单百分比在最近几天总是会剧增。然而,这实际上只是数据更新方式的副产品。如果我们将今天的数据与昨天我们昨天观察到的数据进行比较,那么我们会看到shipped_at列中 NULL 值的百分比实际上是符合预期的。
因此,您应该每天对您监控的每个表格的数据进行快照,并将当前数据与这些快照进行比较,以便排除可能由于即时更新动态而引起的任何更改。由于很难知道哪些表格是原地更新的(许多表格将在没有updated_at时间列的情况下进行原地更新),最好假设正在发生这种情况,并花费额外的计算资源,而不是因此问题发送重复的虚假警报。
请注意,使用这种方法很难实现“温暖启动”,因为您必须等待数据快照,以便可以信任算法不会发现与即时更新动态相关的问题。
列相关性
大多数数据集中都存在大量的相关结构(可以回顾一下图 2-4)。这可能由于多种原因导致。相同的数据可以以多种不同的形式捕获(例如标识符和字符串)。或者可能存在一种层次结构的标识符,它们都被捕获在同一张表中,并用于不同级别的业务报告数据组。此外,表通常表示因果漏斗,在某些事件发生之前必须发生其他事件,这些漏斗将表现为表结构中的相关性。
当列之间存在相关性时,这意味着一个单一的数据质量问题可能会影响所有这些列。如果算法不小心的话,可能会发送多个警报或者建议存在许多单独的问题,而实际上它们都是相关联的。
影响多列的数据质量问题通常发生在数据“分布”管道中。例如,我们可能从一个事件的整数 ID 列开始。然后该列与一个包含位置名称、日期、优先级等元数据的位置表进行连接。如果日志中原始的位置标识符丢失,那么连接将失败,并且所有其他位置元数据也将丢失。
利用表中个别值的 SHAP 值来表彰它们的异常性,您可以利用行级别的相关性将列聚合在一起,并将它们作为单个问题呈现给用户。例如,如果层级结构中的一个级别受到数据质量问题的影响,我们将看到多列存在异常,但都是相同的行。通过这种洞察力,我们可以提供单个异常,而不是给用户发送关于同一事件多次警报。
例如,考虑下面的表格,其中给出了一些存放在杂货店货架上的样品产品数据:
商品 ID |
部门 |
货架 |
产品 |
品牌 |
商品 |
大小 |
|---|---|---|---|---|---|---|
43112 |
冷藏 |
酸奶 |
希腊酸奶 |
Chobani |
0% 原味 |
32 盎司 |
43113 |
冷藏 |
酸奶 |
希腊酸奶 |
Chobani |
0% 原味 |
64 盎司 |
43114 |
冷藏 |
酸奶 |
希腊酸奶 |
Chobani |
2% 原味 |
32 盎司 |
43115 |
冷藏 |
酸奶 |
希腊酸奶 |
Chobani |
2% 原味 |
64 盎司 |
... |
... |
... |
... |
... |
... |
... |
43945 |
冷藏 |
酸奶 |
希腊酸奶 |
Fage |
0% 原味 |
32 盎司 |
... |
... |
... |
... |
... |
... |
... |
在这样的数据集中,异常可能会发生在产品级别(所有的“希腊酸奶”都丢失了),这可能通过从Aisle列派生的特征(“酸奶”异常)、Product列(“希腊酸奶”)或Brand列(一组特定品牌异常)来捕捉。 Department可能过于高度聚合,无法对希腊酸奶的异常敏感,而Item列则过于碎片化,难以用来轻松检测异常。
给定我们的算法为每个单独的记录生成了基于 SHAP 的异常分数,我们可以将聚类算法应用于这些异常分数,以便检测这些列中的异常都发生在相同的一组行上。
模型测试
鉴于所有这些挑战,以及已经相当复杂的算法,您如何确保您构建的模型实际上在真实世界的数据上运行?此外,如何进行迭代改进?
收集基准数据,人类已经标记了什么是异常和什么不是可能乍一看似乎是合理的,但正如我们在本书的其他地方讨论过的那样,创建一个人工标记的数据集,其中评估员判断什么是异常的成本非常高昂(更不用说主观性了)。您需要成千上万个标记的异常才能形成一个强大的基准。
所以,我们需要采取不同的方法。这里的关键洞察力是,实际数据质量问题实际上并不难以编程方式插入数据集。毕竟,问题往往是由代码引起的!我们发现检测合成异常,即“混沌”,是检测真实数据质量问题的良好代理。正如电影《躲避球》中的 Patches O’Houlihan 宣布的那样,“如果你能躲开扳手,你就能躲开球。”
因此,基准测试的算法大致如下:收集一个代表性的表格数据集样本,在引入合成异常之前和之后在这些数据集上运行您的模型,并测量运行时间和评估准确性的统计数据。这使您能够通过更改参数或减少特征等方式来优化您的模型。反复进行这一过程。
让我们谈谈您可以引入的合成异常的种类及其方式,然后继续进行基准测试和微调您的模型。
注入合成问题
“混沌工程”是故意在系统中创建随机失败以测试系统响应的想法。一个众所周知的例子是 Netflix 的混沌猴,这是一个随机终止生产实例以测试网络弹性的工具。
这个想法很好地转化为测试数据质量监控模型。您可以使用 SQL 操纵基准数据集,模拟在生产系统中可能发生的真实数据质量问题。由于真实数据问题往往只影响部分数据,因此重要的是还要变化如何应用合成问题:例如应用于一个段落、随机列、数据的随机百分比等等。然后,您可以根据 ML 指标如灵敏度、特异度和曲线下面积(AUC),以及其他性能特征,如模型所需的时间和检测某些问题相对于其他问题的能力,来衡量您的模型性能。
例子
图 5-4 显示了门票销售数据示例表,每行对应一个音乐会或体育赛事门票的列表。例如,我们可以看到listid编号 43729(最后一行)是在休斯敦德州依靠体育场(可容纳 72k 人!)为 The Who 乐队的四张票,每张票 131 美元(总计 524 美元)的列表。

图 5-4. 门票销售数据示例表。请在https://oreil.ly/adqm_5_4查看此图的完整版。
假设我们知道numtickets列的最大值是 30。测试我们的算法是否能够检测到门票数量分布变化的一种方法是引入一些人为混乱,并将numtickets列的值更改为包含值 40。
仅对最近的日期进行此操作非常重要,因为我们希望这一变化在数据集中表现为突发的异常。此外,为了使这个数据质量问题显得更加微妙,我们将确保混乱仅适用于 30%的记录。我们将包括一个where_sql子句,使混乱仅适用于venuestate = ‘NY’中售出的门票。
在实践中,将此混乱注入表格的 SQL 如下所示:
WITH chaosed_table AS (
SELECT "listid",
"listtime",
"sellerid",
CASE
WHEN `random`() < 0.3 THEN 40
ELSE "numtickets"
END AS "numtickets",
"priceperticket",
"totalprice",
"eventid",
"eventname",
"catid",
"catgroup",
"catname",
"venueid",
"venuename",
"venuecity",
"venuestate",
"venueseats"
FROM fact_listing
WHERE listtime >= Cast(
Cast('2022-05-04' AS DATE) AS TIMESTAMP without time zone
)
AND listtime < Cast(
Cast('2022-05-05' AS DATE) AS TIMESTAMP without time zone
)
AND venuestate = 'NY'
),
all_other AS (
SELECT *
FROM fact_listing
WHERE NOT (
listtime >= cast(
cast('2022-05-04' AS date) AS timestamp without time zone
)
AND listtime < cast(
cast('2022-05-05' AS date) AS timestamp without time zone
)
AND venuestate = 'NY'
)
)
SELECT *
FROM chaos_table
UNION ALL
SELECT *
FROM all_other
这听起来像是一个愚蠢的例子吗?嗯,由于数据质量错误,价格经常会变动,这点可能会让你感到惊讶。例如,看看图 5-5 中的略为高价的航空票。
![略为高价的航空票(Shaun Walker [@sbwalker],Twitter,2023 年 4 月,下午 4:50,https://twitter.com/sbwalker/status/1647024519331168257)](assets/adqm_0505.png)
图 5-5. 略为高价的航空票(Shaun Walker [@sbwalker],Twitter,2023 年 4 月,下午 4:50,https://oreil.ly/BsKtS)。
如果您经常测试模型,将这些操作封装到一个库中将会很有帮助。Anomalo 内部混乱羊驼库中的混乱操作示例包括:
ColumnGrow
将列乘以均匀抽取的随机值。
ColumnModeDrop
删除具有等于给定列的众数值的行。要求众数表示至少一定比例的数据,否则会抛出错误。这旨在防止众数非常罕见的混乱情况。
ColumnNull
将 table.column 转换为 NULL,适用于部分记录。
ColumnRandom
使用随机浮点数或整数替换列中的值,布尔值的 True/False 比例为 50/50,或者对字符串进行哈希处理。
TableReplicate
在表中添加额外的行(从原始表随机抽样)。
为什么是混乱羊驼?嗯,“Anomalo”如果连续说得足够快,足够多次,可能听起来有点像“羊驼”。所以我们选择了羊驼作为我们的吉祥物,并且它们经常出现在我们的内部工具中。

基准测试
基准测试由许多样本数据集组成;我们称这些为回测。每个回测代表数据集在连续几天内的历史样本。对于每个回测,您可以按顺序在每一天运行您的模型。这模拟了数据集的配置以及每天到达新记录的过程。在此阶段,需要捕获的重要数据点是每个表的整体异常分数(与图 5-1 中使用的相同类型的分数)以及学习的动态警报阈值。这将为您提供一个基线,了解模型认为基准数据在引入任何合成异常之前的异常程度。
完成初始运行后,您可以再次循环遍历数据集——但这次每天都会引入一个随机的混乱操作到数据中。然后,您可以重新运行模型,看看它是否能够检测到这些混乱。同样,跟踪异常分数将告诉您模型对每种特定混乱操作的敏感性。
例如,图 5-6 总结了在单个表的回测结果,其中包含从 4 月 29 日到 5 月 28 日的数据。我们从 4 月 29 日开始,为该日期建立我们的模型,记录所有结果,然后依次遍历每个日期,直到 5 月 28 日结束。然后,我们在数据集中注入合成数据质量问题的同时重复此过程。

图 5-6. 回测显示了带有混乱和无混乱情况下的异常分数。随着时间的推移,模型会学习一个用于警报的阈值,因为遇到越来越多的异常。
黄线显示了在引入任何混乱之前模型的异常分数。你可以看到它在 5 月 3 日上升,但其他时间基本保持接近于零。表格在早期可能会有较高的异常分数,因为模型仍在学习哪些列和特征代表着需要抑制以找出真正异常的间歇性变化。得分接近于零表明,一旦这些因素得到控制,数据集非常可预测和规律。
蓝线显示了异常分数的阈值。它从 10 开始,这是最高的异常分数(代表影响 100%数据的极端变化)。我们在这最高值上保持三天,然后开始指数衰减。在 30 天结束时,阈值已经降低到 0.3 以下,这足够敏感以检测到中等异常。
最后,红线展示了在数据集中引入混乱时异常分数的变化情况。第二天,得分跃升至 5 以上——这是一个极端异常,很可能是由重大的混乱操作引起的。但阈值仍然很高(10),因此此问题会被抑制。我们希望在提醒方面保守,特别是在早期阶段。
然而,到了第四天,得分跃升到 6.5 以上,这已经足够高超过了阈值。即使在第一周,数据中足够异常的变化也可以导致模型提醒。随着时间过去,最终到了第 30 天和第 90 天,模型会逐渐校准数据中预期噪声的水平,对混乱更加敏感。
在图 5-7 中,y 轴显示了九个样本数据集的九次回测,每个数据集评估了 30 天(x 轴)。红色方块表示模型发送了提醒,黄色方块表示它接近提醒。灰色方块是模型未提醒的天数。如您所见,早期的提醒并不频繁。
![九个样本数据集的 30 天回测。可从[存储库直接链接]获取全尺寸、全彩色版本。](assets/adqm_0507.png)
图 5-7. 九个样本数据集的 30 天回测。查看此图的完整尺寸版本https://oreil.ly/adqm_5_7。
比较顶部和底部的面板,很明显模型对引入混乱非常敏感,这对每个不同的数据集都是如此。然而,在底部面板中,有许多天仍然是灰色的(没有提醒)——即使我们每天都应用混乱操作。这可能由于几个不同的原因造成:
-
阈值仍然设置得很高,因为我们逐渐将阈值从 10(非常难以提醒)降低到数据集的学习阈值。即使到了第 30 天,这种衰减还没有完成。
-
在某些情况下,我们引入的混乱非常罕见。它可能仅针对 1%的记录,使得异常更难以检测。
-
在某些情况下,我们引入的混乱实际上可能不会改变数据。例如,如果我们将某列中 5%的值更改为 NULL,则如果该列中 99%的值已经是 NULL,这不会有任何影响。
分析表现
要了解模型的表现如何,您可以为整个基准计算不同类型的统计数据,如 AUC、F1 分数、精确度和召回率。
无论您选择查看哪些指标,都有许多不同的方式来分析和解释结果:
-
按数据集
-
模型运行了多少天
-
按照使用的混乱类型
-
按记录百分比应用混乱(混乱分数)
在实践中,我们查看所有这些指标,以及更多内容,以更好地理解模型的表现及其改进可能性。
混乱分数特别有用,因为它让您了解
-
模型在极限情况下的表现如何——当对整个数据集应用混乱时,您期望模型表现非常好。
-
在模型开始无法检测到问题时,考虑到您正在处理的数据样本大小。
在图 5-8 中,x 轴是我们应用给定混乱操作的记录分数(从 1%到 95%的记录),y 轴表示性能统计数据。

图 5-8. 不同混乱分数下模型基准的性能指标。
第一个面板绘制了 AUC 统计数据。这比较了我们对给定日期产生的异常分数(我们的“预测”)与是否在该日期引入混乱的二元“结果”的曲线下面积。AUC 通过在从 0.0 到 10.0 变化的得分的决策阈值上测量假阳性和真阳性率,来分类每个{表,日期}组合,确定是否存在混乱(异常)。当 AUC 接近 0.50 时,模型的表现不比随机猜测好。当 AUC 接近 1.0 时,模型能够完美地检测到数据中的混乱。
我们看到,随着混乱程度从 1%逐渐上升到 50%及以上,AUC 稳步提高,接近 0.80。在实际操作中,由于多种原因,这些 AUC 统计数据未能充分展示模型的表现:
-
某些{表,日期}组合虽然没有混乱,但源数据中确实存在我们需要警示的真实异常。换句话说,并非所有“负面”示例都是真负例。
-
我们的一些混乱操作影响的记录比混乱分数表明的百分比要少得多。该分数对受影响记录的百分比设置了一个最大值——如果我们改变了列的模式,或者一个不频繁的值,或者进行已存在数据中的更改,那么混乱可能无法检测到。
-
我们正在测量模型运行的前 30 天的性能,但在实践中,我们看到模型的性能继续在 90 天内显著提高。
虽然 AUC 有助于理解我们的模型在区分是否应用混乱时的表现如何,但它并不能解释模型在设置阈值时的表现如何。第二面板直接基于决定是否在得分高于或低于学习阈值时发出警报来测量精确率、召回率和 F1 分数。
在这种情况下,精确率衡量的是模型在存在混乱操作时警报的时间比例。这可以帮助您了解假阳性警报的频率。正如您可以在图 5-8 中看到的那样,当混乱影响的记录非常少时,精确率约为 50%。但当混乱影响的记录占比较大时,精确率可以达到 90%。
召回率衡量的是模型能够在混乱操作中警报的百分比。回到图 5-8,您可以看到它开始时非常低(接近 0),但当混乱应用到超过一半的数据时,召回率几乎达到了 50%。同样,召回率可能较低是因为混乱操作很难检测到,这是由于上述原因造成的。
提高召回率的一种方法是对阈值算法进行调整(从较低开始,更快衰减,或者收敛到得分的较低分位数估计),从而使模型对混乱更敏感。然而,这会增加假阳性(和警报疲劳)的可能性,特别是在模型仍在校准阶段的早期。
F1 分数同时考虑了精确率和召回率,并且计算公式为2*((precision*recall)/(precision+recall))。有很多改进可能会提高精确率但不会提高召回率,反之亦然,而 F1 分数则根据综合效果指示改进是否好坏。请注意,在实践中,假阳性和假阴性的成本可以直接估计,并用于决策如何改进和校准模型。
将其与伪代码结合起来
以下是 Python 伪代码的示例,演示了您如何应用我们刚刚概述的方法来评估您的算法性能。假设您从第四章中有detect_anomalies方法,并且有一组表格及其配置信息。然后,它对每个表格进行带有混乱和不带混乱的回测,并总结每个表格的异常分数。然后,根据算法在“预测”哪些结果引入混乱方面的准确性计算 AUC。
请不要太字面理解这段代码,因为它只是为了说明概念及其高层次的结合方式。特别是,我们忽略了算法可能从一次运行到下一次运行中保持状态(例如,阈值计算),并且我们没有为随机混乱生成提供任何详细信息。
我们首先定义如何计算给定日期范围和表格的异常分数:
# General imports
import datetime as dt
from sklearn.metrics import roc_auc_score
# Import hypothetical sub-modules that perform more detailed tasks
from chaos import generate_random_chaos
from prior_chapter import detect_anomalies
def calculate_anomaly_scores(
table: str,
time_column: str,
current_date: dt.date,
prior_date: dt.date,
sample_size: int = 10_000
) -> float:
column_scores = detect_anomalies(
table, time_column, current_date, prior_date, sample_size
)
return sum(column_scores.values())
然后,我们在一系列日期范围内对异常检测逻辑进行回测,以获取带混乱和不带混乱的异常分数:
def backtest(
table: str,
time_column: str,
start_date: dt.date,
number_of_days: int
) -> list[list[float]]:
anomaly_scores = []
chaos_anomaly_scores = []
for day in range(number_of_days):
current_date = start_date + dt.timedelta(days=day)
prior_date = current_date - dt.timedelta(days=1)
overall_score = calculate_anomaly_scores(
table, time_column, current_date, prior_date
)
anomaly_scores.append(overall_score)
# Introduce chaos and recalculate
table_chaos = generate_random_chaos(table, time_column, current_date)
chaos_overall_score = calculate_anomaly_scores(
table_chaos, time_column, current_date, prior_date
)
chaos_anomaly_scores.append(chaos_overall_score)
return anomaly_scores, chaos_anomaly_scores
接下来,我们对多种表格配置运行回测,以评估它们的性能:
def benchmark(
table_configurations: list[dict],
number_of_days: int
) -> list[dict]:
"""
Runs backtests on multiple table configurations to benchmark their performance.
"""
benchmark_results = []
for config in table_configurations:
anomaly_scores, chaos_anomaly_scores = backtest(
config['table'],
config['time_column'],
config['start_date'],
number_of_days
)
benchmark_results.append({
'table': config['table'],
'anomaly_scores': anomaly_scores,
'chaos_anomaly_scores': chaos_anomaly_scores
})
return benchmark_results
最后,我们根据所有表格中的异常和混乱分数计算单个 AUC 指标(作为示例模型指标):
def calculate_global_auc(benchmark_results: list[dict]) -> float:
"""
Calculate a single AUC based on the anomaly and chaos scores from all tables.
"""
all_anomaly_scores = []
all_chaos_anomaly_scores = []
for result in benchmark_results:
all_anomaly_scores.extend(result['anomaly_scores'])
all_chaos_anomaly_scores.extend(result['chaos_anomaly_scores'])
# Create labels: 0 for anomaly, 1 for chaos
y_true = [0] * len(all_anomaly_scores) + [1] * len(all_chaos_anomaly_scores)
# Concatenate scores
y_scores = all_anomaly_scores + all_chaos_anomaly_scores
# Calculate AUC
auc = roc_auc_score(y_true, y_scores)
return auc
改进模型
进行基准测试和分析性能统计数据对理解和调试模型非常有帮助。它也是向用户证明您的系统按预期工作的一种方式。
但是,您可以使用这些数据的最重要的方式之一是验证模型的变化,以确保您在微调中增加了价值。图 5-9 展示了为基准计算的摘要统计信息的示例,其目标是衡量模型变化是否朝着正确的方向发展。

图 5-9. 模型基准的摘要统计和影响。查看此图片的完整版本,请访问https://oreil.ly/adqm_5_9。
图 5-9 中评估的假设更新是一种新类型的功能,允许模型对字符串列中的模式变化(如电话号码、标识符等)更加敏感。此变更显著增加了基准的运行时间,这表明可能需要进一步优化该变更,以避免增加模型的总体延迟和成本。
然而,从积极的一面来看,这一变化显著提高了精度和召回率,减少了误报。AUC 也有所改善,尽管在绝对基础上看起来改进的百分比很小。但是,如果我们问的是 AUC 相比 0.5 提高了多少(因为 0.5 表示随机行为),AUC 的改善实际上是(0.624 - 0.5)/(0.617 - 0.5) - 1 = 5% 更好,这是显著的。
结论
我们探讨了在构建模型时可能需要注意的一些真实世界数据属性——比如数据的相关性或就地更新的事实。我们还详细介绍了如何通过向样本数据集注入混乱来对模型进行基准测试。这些测试的结果将帮助您衡量模型的性能并随时间进行迭代。
建立一个能够适当地警示真实世界数据问题的模型并不容易——既不能错过重要问题,也不能因小而过警报。然而,一旦你拥有了高质量的模型,真正重要的是如何利用它来赋能负责数据质量的人员。在下一章中,我们将解释如何利用你的模型输出来构建有效的通知,帮助用户彻底了解数据异常变化的原因。
¹ 如果不这样做,你可能会从数据集中删除一个数据质量问题!
第六章:在避免警报疲劳的同时实施通知
如果监控系统在出现问题时没有通知你,那么它有什么用呢?然而,警报既是监控的精髓,也是它的致命弱点。正确地执行,通知将通过适当的渠道将信息传达给正确的人员,帮助他们理解问题的严重性,甚至指出快速解决问题的根本原因。但是,如果执行不当,通知将会向太多人发送,缺乏上下文,并且难以采取行动。它们将是不可信的,并最终被忽视。
警报疲劳是数据质量监控工作失败的最大原因之一,尤其是在企业扩展时(参见侧边栏“警报疲劳”)。如果有数十人参与数据质量工作,并且成千上万的表格触发了警报,那么如果这些警报没有帮助、令人困惑或嘈杂,那么大量的员工时间和精力将被浪费。
在本章中,我们将分享多种技术,帮助您确保通知能够赋予团队解决数据质量问题的能力。我们将介绍问题解决过程中的步骤以及如何设计通知以在每个阶段(包括根本原因分析)提供帮助。我们将讨论如何找到特定通知的正确受众和适当的传递机制。我们将探讨许多避免警报疲劳的策略,以便您的系统尊重可能是我们最宝贵的人力资源之一:我们的注意力。
如何通过通知促进数据问题响应
你可以随时监控数据质量,但只有在监控结果产生积极作用时,你才能真正改善数据质量。通知是你的监控系统和其试图实现的结果之间的关键联系。它们使人类能够采取步骤,以真正理解和解决数据质量问题。
不管通知本身的详细内容是什么,我们稍后会讨论,响应通常遵循相同的步骤。当我们讨论构建良好通知的要求时,这些步骤对于我们来说是很重要的。高质量的通知将在响应过程的每个阶段赋予人类能力。
分类
分类步骤可以总结为“判断问题是否值得关注”。例如,对于电子商务业务而言,一个令人关注的警报可能是跟踪 Android 设备上结账转化事件数量的大幅下降。另一方面,在假日期间整体结账转化事件数量的减少对业务可能并不那么令人关注,除非是黑色星期五。
对于从第三方获取信用卡数据用于欺诈模型的银行,高优先级问题可能是跟踪近期交易的某一列的 NULL 值突然增加。NULL 值的突然增加对模型尤为灾难性(见章节“NULL 增加”),业务将希望快速跟进这个问题。相反,如果他们在推出针对新客户段的产品后看到信用评分分布的变化,可能就不会那么担心。
请记住,自动化数据质量监视器正在寻找数据值中的显著且意外的变化——它们并不关心这些变化是否确实对业务有影响。因此,在本章中,我们将花费大量时间讨论如何使通知更容易进行分类,甚至在许多情况下静音某些类型的通知,以免团队花费大量时间查看低优先级的警报。
路由
一旦确定了问题的严重性,下一步就是决定通知谁,以便进行进一步的调查或解决方案。这一过程在很大程度上取决于您的数据组织结构。表 6-1 显示了几个不同功能团队的示例以及它们可能参与解决不同类型问题的方式。
表 6-1. 示例数据质量问题映射到团队
| 问题 | 负责团队 |
|---|---|
| --- | --- |
| 负责应用程序中某些活动的服务偶尔失败,导致数据丢失。 | 工程基础设施 |
| 由于代码更改导致应用程序在某些情况下记录重复事件。 | 产品工程 |
| 第三方提供商已更改其 API,并未就此变更进行沟通。 | 数据合作伙伴关系 |
| 更改广告活动运行方式的配置更改删除了跟踪信息。 | 营销运营 |
| 以前每小时运行一次的 ETL 过程现在计划改为每六小时运行一次。 | 数据工程 |
使用CASE WHEN SQL 子句重新映射类别的转换已更改,一些类别被删除,导致 NULL 值。 |
分析工程 |
路由可能非常复杂。根据领域的不同,您可能会有不同的数据质量问题的受众;例如,关于广告活动的数据与关于客户的数据可能有不同的团队。有时,您可能需要涉及多个团队以提供所有必要的背景信息。本章后面,我们将讨论如何确保通知到达合适的人员,同时避免创建过于广泛的受众的错误。
解决方案
这是修复数据质量问题(震惊)和/或回填历史数据(疤痕)所需的实际工作。通常会在诸如 Linear、GitHub Issues 或 Jira 之类的单独系统中进行跟踪。解决过程极大地取决于数据质量问题是如何引入的,以及组织是否对数据的生产、传输或转换有任何控制。在本书中,我们不会过多讨论解决的具体细节,但稍后会讨论根本原因分析如何帮助解决问题。
文档
最后,在关闭问题时,记录解决问题所采取的任何行动(如果有的话)至关重要。许多问题会以某些微小变化的形式再次出现,过去如何处理问题的历史记录可以成为未来可能类似的问题的重要信息库。此外,解决数据质量问题远非一帆风顺,有时会出错——修复背后的逻辑可能不合理或可能导致意外副作用。没有文档记录,要想回头撤销或以其他方式纠正错误的修复将会很困难。
没有通知就采取行动
在进一步进行之前,我们应该承认,通知不一定是解决数据质量问题时采取行动的唯一触发器。让我们探讨一下在没有通知的有限场景下,您可以采取行动的情况。
有些团队直接将数据质量监视器集成到其编排工具和流程中(例如 Airflow、dbt)。每次将数据加载到暂存环境时,他们都会运行一系列数据质量检查。如果检查通过,数据将被复制到生产环境并用于下游用例的“发布”。如果检查失败,自动化脚本可能会清理一些数据质量问题,例如重复记录。例如,您可以想象一个规则,根据时间戳仅保留最近的客户记录。
这些自动化测试在某些场景下非常有价值。例如,它们可以阻止数据发布,在某些情况下,晚发或者不发数据要比发错数据好(例如用于做不可逆决策)。或者应用的“修复”可能相当于“重试”。特别是对于数据新鲜度或者体积问题,有时候稍等片刻问题就会自行解决。在复杂的分布式编排中,确保一切都按照适当的计划进行可能很困难,因此在系统中内置重试功能可以使其更加健壮。
但当基础数据质量问题真正只是糟糕的数据时,用修复数据的方法掩盖问题通常不是个好主意。虽然它可以确保下游系统按预期工作(数据加载到一个类型字段中;在下游没有抛出异常),但实际上只是掩盖了问题,防止任何人意识到它的存在。它还会引入可能以意想不到的方式影响决策或 ML 模型的数据偏差。
还有一些其他情况,你可能不需要设置通知,因为你直接检查系统的输出。例如,你可能会使用 API 与你的数据质量监控系统交互,因此可以完全控制其响应。如果你正在执行数据迁移,并希望通过命令行运行检查并检索其状态,这可能非常有用。或者,你可能会运行检查生成仪表板,计划的运行后手动检查。然而,这些情况从定义上讲是手动的,并且不可扩展。
现在,让我们回到通知问题上,这是监控结果转化为改进数据质量行动的主要手段,也是本章的重点。
通知的构成
鉴于解决过程中需要采取的步骤,设计数据质量监控系统时我们要问的问题是:如何创建通知,以尽可能地促进这些步骤,使问题易于分类、路由、解决和记录?
让我们从高层次定义通知本身的主要组成部分开始。接下来,我们将进行所有不包括通知内容的决策,例如如何传递通知、避免警报疲劳以及为根本原因分析提供额外上下文。
对于这堂解剖课,图 6-1 展示了我们将一同剖析的一个 Slack 通知样本。

图 6-1. 数据质量问题的 Slack 通知样本。在https://oreil.ly/adqm_6_1查看这幅图的完整版本。
可视化
根据 Jill Hardy 指出,一个可视化图表胜过一千个数据点。¹ 图形可以包含大量关于基础问题的信息,问题的严重程度以及可能需要的下一步措施。
我们每个通知中只包含一个可视化图表,其类型随检查和发现的问题而异。点击“查看详情”并转到完整报告中,可以找到更多详细信息。
可视化不仅显示当前问题,还提供一些上下文或历史。可能有许多用户会看到通知,但可能不是监控平台的活跃参与者。请记住,如果可视化太复杂,用户将无法快速理解。
操作
重要的是立即使通知变得可操作。我们建议从通知中支持三种不同的操作(您可以在图 6-1 的底部看到这些操作按钮):
查看详细信息
允许用户调查问题并更多地了解背景和历史。此操作将用户直接带入数据质量监控平台,他们可以看到额外的可视化、记录示例、采取的行动摘要等。
编辑检查
引发编辑配置,用于发送此通知的检查。这使用户可以轻松地进入并更改配置,以便检查更好地针对他们关心的问题或将来少发通知。
分类
将用户直接带入平台上的分类流程,他们可以执行以下操作之一:
-
确认:通知其他人已经意识到问题并正在进一步调查。
-
解决:解决问题,无论是因为已修复还是因为不需要解决或预期内。
-
提交工单:为额外的工作创建一个工单,他们可以直接通过 API 在平台上执行,或者在像 Jira 这样的工单系统中跟踪。例如,工程师可能需要更改事件记录方式以修复此基础问题。参见图 6-2,显示了关于分类选项的截图。

图 6-2. 示例分类选项。
文本描述
除了可视化外,一些文本信息可以帮助更多地了解检测到的问题背景。我们通常推荐三种不同的文本组件:
标题
用户定义的字符串,表示检查的意图或目的,通常由用户在创建检查时提供。这有助于将额外的业务、数据或工程上下文传递给最终接收警报的人员。
摘要
自动生成的警报摘要,识别发现的问题性质并量化其重要程度。
历史记录
过去触发警报的次数。在调查问题时非常有帮助。这个警报已经静默了几百天吗?天啊,一定发生了什么重大的事情!相比之下,这是连续第四次触发警报吗?这可能意味着我们仍然需要修复一个持续存在的问题,或者可能需要重新配置检查本身。
谁创建/最后编辑了检查
在操作按钮下面,我们识别了首次创建检查的人和最后编辑检查的人。这是有帮助的背景信息,因为接收警报的人可能想要向这些人提问,例如为什么他们首先设置了这个检查或者谁可以帮助进一步调查或解决问题。
传递通知
无论您的通知设计得有多么周到,如果它们发送给错误的人或者进入一个没有人检查的收件箱,它们都不会产生结果。因此,您的监控平台必须与多种不同的交付渠道集成,并允许用户配置通知的交付方式。您可以通过查看图 6-3 中的下拉菜单来了解可能的各种渠道的情况。

图 6-3。示例警报和通知目的地。
通知传递的三个维度真正存在:(1) 谁会收到通知,(2) 他们会如何收到(在他们的电子邮件收件箱?Slack?他们会被呼叫吗?),以及(3) 他们会在什么时候收到(立即还是总结中?)。
通知受众
应该通知谁是一个关键决策,对于减少警报疲劳至关重要。一个大公司可能有数百名对各种数据质量问题感兴趣的人。如果每个人都收到每个警报,那将会完全不堪重负!
在考虑受众时,要专注于所有权和背景信息。通知只有在采取行动时才会创造价值。因此,接收通知的人应对相关表的数据质量有很高的所有权。他们必须有动力来负责通知及其分类和路由。您还需要确保已经包括了能够提供必要背景信息的人员。在某些情况下,可能需要多个人来理解问题并决定接下来应该采取什么步骤。
假设您已控制了所有权和足够的背景信息,那么接下来您希望将接收通知的受众最小化。通知会分散注意力:每个看到它们的人都必须停下手头的工作并处理信息。您可能有很多方面对数据质量感兴趣的各方,但这并不意味着他们都应该被通知。如果他们对响应不是必不可少的,给他们其他发现相关信息的手段,比如报告、仪表板或总结。
更具体地说,定义受众的最常见策略是按表分组,然后按照对这些表感兴趣的用户域分组。这确保了每个主题领域(例如市场营销、财务、增长、运营等)只接收他们关心的表的通知。不同行业的域因组织团队的方式而异。例如,Jeremy 在 Instacart 工作时,领域包括物流、目录、广告、消费者增长和消费者应用。
您还可以根据检测到的问题类型确定受众。数据工程可能对表的新鲜度和量最感兴趣,而分析和业务用户可能最关心关键指标的变化。
无论如何,一个基本的经验法则是将任何给定的警报发送给一个,而且只有一个受众。这样可以确保您保持高度的责任感,并且针对每个问题进行单线程对话。否则,您可能会陷入两种糟糕的情况之一:
低所有权
多个受众收到每个警报,并且每个组中的个人都认为另一组正在查看警报。
重复的努力
多个受众收到警报,现在有两个独立的对话和工作流用于分析和解决潜在问题。
通知渠道
不同的受众将会有不同的偏好,以何种方式接收通知。有些类型的通知更适合通过电子邮件而不是紧急提示。以下是您希望您的数据质量监控系统集成的主要渠道,以及它们在大多数企业中的使用方式。
电子邮件
电子邮件,作为最常见的异步通信形式,通常用于发送摘要通知(例如每周问题和状态列表),不打算迅速回复。但是,在某些组织中,电子邮件仍然是主要的通信形式,因此电子邮件警报可以成为主要渠道。
实时通信
如今,大多数团队希望通过像 Slack 或 Microsoft Teams 这样的实时通信提供商接收通知。通常,团队会希望设置一个或多个群组(例如 Slack 频道),在这些群组中相关受众接收其数据质量通知。
实时通信为一些节省时间的策略提供了便利,其他方式难以实现。例如,在 Slack 上,许多团队使用表情符号反应来帮助快速分析和管理通知状态,如图 6-4 所示。从通知本身开始,还可以轻松启动一个对话线程,以跟踪调查/分析或解决方案,同时保持共享的上下文。

图 6-4。在 Slack 或 Microsoft Teams 中对警报的常见表情符号反应示例。
PagerDuty 或 Opsgenie 类型的平台(警报,值班管理)
对于最重要的检查(这些应该很少见),您可能希望通过像 PagerDuty 或 Opsgenie 这样的警报或值班系统“唤醒”指定的人员以响应问题。
票务平台(Jira,ServiceNow)
在罕见的情况下,您甚至可能希望通过直接将通知插入到票务平台来为某人创建工作项,但我们建议在创建工作票之前,让人类中介评估和分类问题。否则,您可能会得到无法执行或重要性不大的工单。
Webhook
Webhook 是通过网络通知另一个任意系统的通用手段。通过支持 Webhook,您确保用户可以将通知路由到不适合前述类别的任意系统。例如,一些公司可能有他们购买或内部构建的企业通知路由系统,他们希望将警报发送到这些系统,然后根据如何向最终用户发送这些通知应用额外的业务逻辑或规则。
通知时机
通常有两种策略决定何时发送通知:
-
一旦检查完成(实时),即时发送失败的通知,因此通知渠道变成了随着计算而产生的“日志”。
-
等待特定数据集(表格,模式或其他分组)的所有检查完成,然后发送包含所有通过和/或失败检查摘要的单个通知。
几个原因推荐第一种方法。首先,它允许用户在识别问题后尽快接收通知,从而缩短响应时间。特别是当检查应用于大数据集和/或利用机器学习时,不同检查的运行时间可能会有很大差异。如果等待所有检查完成以发送单个摘要通知,可能会延迟某些通知的到达时间数小时,加剧数据质量问题的伤害。
第二点是,通常即使没有数据质量问题,也会发送汇总通知。这些“全绿”警报可能令人放心,但它们需要用户消耗不需要采取行动的内容,这可能无意中加剧警报疲劳。当包含重要失败的摘要到达时,人们是否仍会关注?
最后,一组给定的数据可能存在多个数据质量问题。我们发现每个通知单独到达是有价值的,这样关于不同问题的讨论可以在相应的数据质量通知下进行。使用汇总警报时,可能会导致用户讨论或分类多个不相关的问题,形成混乱的线程。
避免警报疲劳
如何避免在设置数据质量监控系统时用噪音通知过度冲击您的用户是一个最棘手的问题之一。在这一章节中,我们将探讨更直接的技术,以限制团队接收的低价值警报数量。
按正确顺序安排检查
在许多监控系统中,如何安排检查是许多误报通知的最大原因之一。这是因为安排数据质量检查有两种简单的方法,而这两种方法都有问题。
第一种方法是在处理完一组新的进入数据后自动运行所有检查。例如,在更新表的 Airflow 有向无环图(DAG)结束时,您可以通过 API 自动触发针对加载到表中的最新日期的数据质量检查。第二种简单的方法是按照设定的时间表每天运行检查。例如,您可能期望第三方数据每天早上 5 点前到达,因此您会在东部时间早上 7 点运行所有数据质量检查。
这两种方法的问题在于,您通常会在不完整的数据上运行检查。如果按照设定的时间表运行检查而数据延迟,那么所有检查可能会失败或抛出异常,因为没有数据。而且无论哪种情况,当您运行检查时数据可能尚未完全交付,这意味着跨表比较或聚合数据的验证规则几乎肯定会失败。您正在监控的任何指标看起来也会异常。不完整的数据几乎总是有偏差的——无论是因为一天中的时间、可用或加载的子集,还是显而易见的总体数据量。
那么,如何避免在数据还没有完全到达时运行检查,并创建大量噪音警报呢?最好的方法是首先设置检查,以查看特定数据分区(通常是以分区时间列指定的一天或一小时的数据)内是否具有足够的新鲜度和数据量。然后,在这些检查通过后,再运行深度数据质量检查。
通过数据质量监控平台解决这个问题的一种方法如下(见图 6-5)。作为系统行为的一部分,设置一个“数据新鲜度”检查,查找每个日期分区内的记录。由于并非所有数据都以相同的频率交付,此检查应学习和适应变化,例如,如果数据通常不会在某些周几到达。一旦“数据新鲜度”完成,运行“数据量”检查,确保记录的数量在预期的特定时间段内的预测分布范围内(使用时间序列模型来控制季节性、趋势、方差变化等)。仅当数据新鲜度和数据量运行后,才应启动该数据新分区的深度数据质量检查。

图 6-5. 在正确顺序中安排数据检查。数据新鲜度和数据量检查每 15 分钟运行一次,并且“门”控制下面显示的深度数据质量检查。所有其他检查(缺失数据、表异常等)只有在我们确定它们不会因新鲜度或数据量问题触发误报通知时才运行。
使用机器学习对警报进行聚类
警报疲劳的另一个来源是系统触发了源自同一问题的重复警报。造成这种情况的原因有几个。首先,数据新鲜度和数据量问题可以“级联”到依赖上游表的派生表中。其次,表中可能有多列彼此密切相关,并且可能都反映同一潜在的数据质量问题。最后,外生效应——可能表现为数据质量问题,但实际上是产品行为或产品正在交互的世界中的变化——可能会在多个列或表中引起多种相关效应。
这意味着聚类或去重警报是监控系统的一个重要特性。当相同表内发生重复警报时,您可以使用机器学习对其进行聚类。假设您的数据质量问题可以映射到个别记录,您可以在问题的上下文中将每条记录分类为“良好”或“不良”。然后,您可以计算“不良”和“良好”记录在多个数据质量问题中的相关性,并确定它们是否可能标识出相同的一组不良记录。正如在第四章中所解释的那样,能够为其检测到的异常分配信用的机器学习算法可以类似地将问题聚类在一起。
一些团队将使用数据血统来跨多个表聚类数据质量问题。图 6-6 展示了血统的截图。当表格的新鲜度或容量出现问题时,您可以向上查看,看看供给此表的表格是否也在失败,并以此方式聚类警报。

图 6-6. 展示问题如何影响上游和下游表的血统。在https://oreil.ly/adqm_6_6 可查看此图片的完整版本。
抑制通知
管理警报疲劳的一大部分是在其达到用户之前抑制通知。让我们探讨几种实现这一目标的方式。
优先级别
抑制通知的一种方法是要求用户设置不同检查的优先级别。

图 6-7. 数据质量检查的优先级别。
如图 6-7 所示,我们建议三个优先级别:高、普通和低。Anomalo 平台以以下方式实现这些优先级别,尽管您可能发现需要不同的解释:
高
这些检查将在每次失败时警报用户,以及在首次通过后重新失败时。
普通
普通检查在连续三次失败后首次警报,会抑制额外的重复警报。与高优先级检查类似,当这些检查在失败后重新通过时也会发出警报。大多数检查应该属于此优先级别,也是新检查的默认设置。
低
当这些检查失败时,它们永远不会警报用户。此优先级别对于调试数据问题或者想要记录特定类型的数据质量问题但不希望收到通知时非常有用。
连续再训练
我们在第四章中描述的数据质量监控的机器学习方法包括在每天新数据到来时重新训练模型。这样做的好处是自动抑制“已知问题”的警报,否则可能会继续通知用户。
如果在第 1 天出现了突如其来的新问题,例如某列分布的变化,模型将在第 1 天发出警报。但是在第 2 天,我们将使用第 1 天的数据重新训练模型。因此,该模型基本上会认识到第 1 天代表了这个数据集的“新正常”,并会抑制出现在第 1 天的问题的警报。
缩小模型的范围
为了减少总体接收到的数据质量警报数量,将监控 ML 应用于真正关心的表格范围内可能是有帮助的。参考表格 3-1 ,了解如何将 ML 监控应用于大数据仓库中的重要表格的示例。
对于扫描整个表格的基于机器学习的方法,你也可以将列限制在感兴趣的那些列上。数据往往会随着时间的推移而迁移其模式,新增列和废弃其他列。为了避免造成下游故障,大多数系统会保留旧的列并始终添加新的列,而不是修改旧列。这可能导致许多已被废弃的列,应该从监控中排除,因为它们可能会导致不必要的额外通知。
最后一个非常有效的缩小完全自动化监控范围的方法是查看命中数据仓库的 SQL 查询日志。由仪表板、机器学习模型或特定分析查询生成的 SQL 查询是显示出最重要数据的线索(我们称之为数据中的“热”)。通过解析这些查询并确定使用最多的表和列,自动化方法可以进一步缩小范围,仅关注组织中最重要的数据。
使检查 less sensitive
最后,为了让用户能够手动调节特定检查的敏感度,以便更少频繁地发出警报,这非常有帮助。例如,您可以让他们扩大可接受坏值的范围,或者他们可以决定监视器是否仅在表格中出现新坏记录时发出警报。
对于利用时间序列动态设置范围的检查(例如我们在第二章中讨论的指标监控),用户还可以改变置信区间,使这些检查 less sensitive,如“指标监控”中所示。

图 6-8. 警报的置信区间选项。
置信区间可以对通知的敏感性产生很大影响。图 6-9 显示了具有左侧 95% 置信区间和右侧 80% 置信区间的时间序列指标监控检查。

图 6-9. 比较不同置信区间。
80% 的置信区间意味着,平均而言,我们预期最新的度量值将在置信区间内的时间占 80%。这意味着它将有 20% 的时间超出此区间。平均而言,这意味着您每 5 天将会收到一次警报(1 / .2 = 5)。
相比之下,在 99% 的置信区间之外的情况只会发生 1% 的时间,这意味着你每 1 / .01 = 100 天可以预期会收到一次警报。
请注意,实际情况下可能会有频繁发生警报的时间段,也会有长时间没有警报的时期。
不应该屏蔽的内容:预期变更
有时候您预期数据会发生变化。例如,您可能计划在某个表中弃用一个列,因此您预期它的所有值明天将变为空。或许您会自然而然地认为,也许您应该屏蔽此类变更的警报,例如向监控系统提供预期变更的列表。
通常情况下,这不是一个好主意。维护一份预期变更列表相当困难,并且很难将每个变更映射到特定的表、列、变更类型和变更生效的时间点。如果这种映射不精确,你可能会冒着未能屏蔽预期变更或屏蔽意外变更的风险。这两种情况都会对信任产生后果。
实际上,我们发现允许预期变更继续触发数据质量检查更好。警报将验证变更确实发生,并可以提供可能有用的上下文(根本原因分析、时间等)。此外,通知将作为变更及其影响的保存日志,这对未来的分析师特别有帮助,尤其是如果有任何意外后果。
自动化根本原因分析
通常在解决数据质量问题之前,您需要准确定位问题发生的数据位置。时间在流逝——只要问题未解决,数据损伤只会加剧,随着时间的推移,这将花费企业更多的金钱和资源。但传统的根本原因分析非常耗时,需要分析师仔细查阅记录并执行定制的复杂 SQL 分析。
想象一下,您有一个数据质量检查,用于验证某个列永远不会为空。突然之间,该检查失败了,您想要找出在拥有数百万条记录的表中所有空值来自何处。如果您的通知能够伴随自动根本原因分析,会怎么样?
实现这一点的一种方法是使用第四章中描述的无监督机器学习方法来解释好坏行之间的差异。然而,在实践中,用户最关心的是是否存在特定数据段最能解释坏数据来源的情况(例如,特定地理位置、事件类型或产品线),并且他们希望得到尽可能清晰的解释。我们发现,可以通过更简单、计算量较少的方法实现这一目标。换句话说,您可以对数据进行采样,分割数据(“WHERE column = x”),并独立分析每个数据段。
要理解这个过程,让我们从考虑图中的矩形开始,Figure 6-10 代表所有数据。 A 和 B 部分是数据通过检查的地方。 C 和 D 部分是数据未通过检查的地方。问题数据段是右侧的 B/D 区域,与左侧的 A/C 区域中的其他数据进行比较。

Figure 6-10. 当查看特定段时,表中可能出现不良数据的方式。
在段内的不良行的百分比,与总数据中的不良行相比,为 D / (C + D)。段内的良好行的百分比,与总数据中的良好行相比,为 B / (A + B)。然后我们可以比较这些百分比。我们寻找的是不良行在整体人群中显著过度表现的样本,以及良好行显著低估的情况。
为了进一步解释,Figure 6-11 显示了段可能落入的四个类别。如果一个段包含的不良数据比整体人群几乎相同的比例(左上),它很可能与事件无关。如果一个段包含所有的不良数据,但也包含大量的良好数据(右上),它可能有助于指出问题的方向,但不足以精确定位问题。如果一个段大部分是不良数据,但同时也缺少很多不良数据(左下),这是无法理解问题的。最后,如果一个段包含所有的不良数据并且几乎没有其他数据(右下),那么你很可能找到了根本原因。

Figure 6-11. 不良数据可能出现在与片段相比的不同可能位置,以及相应的影响。
由于早先描述的百分比计算非常快速,您可以自动化此过程并提供可视化,显示最可能是根本原因段的部分。例如,图 6-12 显示了可能导致数据检查失败的数据段(在本例中,表跟踪了票务销售,票价为 NULL 的数量令人担忧)。顶部段是我们的主要嫌疑:它覆盖了所有的坏行和极少量的良好行(浅灰色矩形)。接下来的三个段也覆盖了所有的坏行,但良好行的比例显著更高,使它们更具指向性而非概率性。显示的最后一个段,其中eventname = "Il Trovatore",值得注意,因为它只包含坏行。但由于它的坏行总数非常少,这个段无法理解其根本原因。
请注意,由于您已经对数据进行了采样并将其分为良好和坏行,因此您还可以使这些样本可供探索和/或导出进行进一步分析,如图 6-13 所示。

图 6-12. 包含大量坏记录的数据段。在https://oreil.ly/adqm_6_12上查看此图的完整版本。

图 6-13. 良好和坏行的样本。在https://oreil.ly/adqm_6_13上查看此图的完整版本。
结论
在实施自动化数据质量监控系统的通知时,您需要做出许多设计决策。当这些通知需要在大型数据仓库和多个团队之间扩展时,问题变得特别复杂。我们希望本章为您提供了一个良好的起点,了解通知内容应包含哪些内容以便采取行动,它们如何传递给适当的受众,以及您应该考虑在哪里构建调节旋钮和防范警报疲劳的防护栏。正如您所见,通过深思熟虑的自动化,您可以做很多事情,甚至可以在通知中直接帮助进行根本原因分析。
通知是用户如何采取数据质量问题行动的核心,以解决数据冲击和治愈数据伤痕的方式。但正如我们将在第七章中看到的集成中所述,自动化数据质量监控系统还可以通过不同部分扩展到您的运营中,建立对数据的信任。
¹ Jill Hardy,“为什么可视化值千言万语”,Looker(博客),2019 年 7 月 18 日。
第七章:将监控与数据工具和系统集成
正如我们在第一章讨论的,数据质量监控并非孤立存在,它是组织数据堆栈的关键部分,包含许多不同的系统和组件。这意味着集成是任何数据质量监控平台的重要部分。有两种类型的集成:基础功能和差异化功能。基础功能的集成与数据仓库/数据湖和 ETL 工具是必需的,以便您的平台能够检测静态数据和动态数据的数据质量问题。
然后还有差异化功能:这些集成并非必要用于检测数据质量问题,但在提供大量次要价值时非常重要。例如,与数据目录、分析或商业智能(BI)工具的集成。这些确保当某人在数据质量监控平台的数据 UX 之外的不同上下文中查看数据时,他们可以立即了解该数据的质量是否高。
在本章中,我们将探讨如何与以下工具集成:
-
像 Snowflake 和 Databricks 这样的数据仓库
-
像 Apache Airflow 和 dbt 这样的数据编排器
-
像 Alation 和 Databricks Unity Catalog 这样的数据目录
-
像 BI 仪表板和机器学习模型这样的数据消费者
我们将解释为什么您可能希望与每类工具集成,并逐步介绍成功集成所需的步骤。但首先,让我们全局看一下数据质量监控如何融入现代数据堆栈。
监控您的数据堆栈
一个企业的数据堆栈通常包括以下系统:
-
事件、日志、SaaS 应用程序和第三方数据源等原始数据源
-
数据存储工具,如云数据仓库或数据湖
-
用于 ETL 数据从一种格式转换为另一种格式的编排工具;例如,为了准备操作数据以供分析工具使用
-
数据目录和治理工具用于探索可用数据、理解血统和审计更改
-
专门用于机器学习的 MLOps 基础设施
-
用于从数据中获取洞察的 BI 和分析工具
大多数企业希望在其堆栈的多个位置部署数据质量监控,而不仅仅是一个位置。例如,他们可能希望平台持续监控数据仓库中的关键表,同时将平台的检查集成为其编排工作流程中的任务,以确保在引入数据质量问题时无法完成转换。
此外,即使在这些地方没有积极发生检查,堆栈中的某些位置可能也会受益于数据质量信息。例如,如果数据质量发生重大变化,您可能希望自动重新训练 ML 模型。或者,您可能希望 BI 分析师能够看到供应仪表板的数据存在未解决的质量问题时。
尽管数据堆栈中的大多数工具都提供了发送和检索信息的接口,但它们看起来大不相同,并且数据本身将以不同的格式存在;例如,没有标准的方法与每个数据仓库集成。在数据质量集成方面,数据生态系统已经有了一些鼓舞人心的向标准化的运动,例如 Alation 的开放数据质量倡议和 dbt 的语义层。尽管如此,集成仍然需要大量的工程工作和强大的 API 支持。
使事情变得更加困难的是,大多数企业在数据堆栈的每个部分都尚未确定单一的工具。通常情况下,不同业务垂直领域中运行的独立数据团队已经演变出使用不同的工具集。
如果您正在内部构建数据质量监控平台,您将希望审计这些工具,估计与每个工具集成所需的时间,并优先考虑您的努力。这可能会影响您的自行构建与外购决策(详见第八章以获取更多详细信息)。另一方面,如果您正在与供应商合作,您将希望确保他们支持与您关心的工具的集成,而不会给您的团队增加大量工作量。
数据仓库
数据仓库(我们简单地使用这个总称;它包括其他形式的存储,如数据湖)是一个基础的集成。监控进入仓库的数据至关重要,因为这是数据以其预期的“静态”格式存在的中心来源。此外,数据仓库还向下游的数据消费者(如机器学习模型和分析仪表板)提供数据。
大多数大型企业没有围绕单一的数据仓库进行标准化,通常需要支持多个数据仓库的集成。这可能包括传统的本地数据仓库(例如 Teradata),如果您的业务计划无限期使用其中之一或正在迁移到云上。许多公司还希望监控来自其实时事务性数据库的数据(例如 Postgres、SQL Server、Oracle)。一些组织还选择同时使用多个云数据仓库(例如同时使用 Snowflake 和 Databricks)以充分利用它们的相对优势。
当我们稍后讨论时,使用无监督机器学习进行数据质量监控在一个组织拥有多个数据仓库时尤为有用,因为它可以检查数据是否准确地在这些仓库之间复制。
与数据仓库集成
后端集成的详细信息将根据数据仓库的不同而有所不同。大多数数据源支持基于 SQL 的查询,这通常是通过 API 进行数据测试、计算统计信息或从底层数据中提取样本的方式。然而,SQL 方言可能差异巨大,用于规则、统计或样本的 SQL 也需要在每个支持的平台上进行调整和测试。
此外,不同的平台具有不同的可扩展性要求——例如,在 Presto 中,每个查询中都包括基于时间的WHERE SQL 过滤器至关重要。在 BigQuery 中,没有一种无偏的方式可以随机抽样数据,而不需要扫描大量行。传统或事务性数据存储可能无法很好地响应来自自动化监控的查询负载,并且监控系统可能需要能够抵御短查询超时或长查询队列;在这种情况下,优化 SQL 查询变得至关重要。
一般情况下,用户需要以下内容来启用监控:
网络连接性
您可能需要将您的监控应用程序的 IP 地址添加到数据仓库的允许列表中。
数据库的只读访问凭证
我们建议为监控创建一个专用服务账户,该账户具有对您要监控的表的只读访问权限。
此外,对于许多传统数据仓库,用户只需提供主机、端口、数据库名称、用户 ID 和密码。Snowflake 只需要帐户 ID 和数据库名称,如图 7-1 所示。要连接到 Databricks,用户需要生成个人访问令牌。

图 7-1. 设置 Snowflake 集成。
通过适当的访问权限,在后端,您需要设置扫描数据仓库以获取每个可查询对象的过程,这些对象是凭证有权访问的,包括表、视图和物化视图。这些对象应该组织和呈现给用户,以便他们可以配置监控表。参见图 7-2。

图 7-2. 按数据源筛选。查看此图片的完整版本,请访问https://oreil.ly/adqm_7_2。
正如第 2 章所述,从数据仓库提取元数据也很重要,比如表上次更新的时间以及上次更新的数据量,这对可观察性很有用。元数据还用于血统,这对根本原因分析很有用。现代化的云数据仓库将通过 API 公开大部分此类信息,例如 Databricks 的数据血统 API。提取和跟踪元数据比在整个数据仓库上运行无监督的机器学习更具成本效益,因此,正如本书其他地方提到的那样,大多数组织将使用基于元数据的可观察性来监控大部分表格,将深度数据质量监控保留给最重要的表格。
在数据仓库中,您应该多频繁地扫描新对象和元数据?我们建议每天运行此过程,以检测新表和表结构的更改,因为这与大多数数据质量检查发生的频率相匹配。如果您预期会有需要实时更新并在工具中看到这些变化的情况,则提供一种让用户手动触发数据仓库刷新的方法可能会很有用(例如,通过 REST 端点)。
要进一步说明,图 7-3 展示了 Anomalo 架构如何与典型部署中的所有其他系统集成的简化示例,并清楚地划分了运行在数据质量监控平台内部的内容(虚线框)。该平台本身可以在单个虚拟机上运行,使用开放容器倡议(OCI)容器(例如,通过 Docker),或者为了水平扩展,可以使用 Helm 图表在 Kubernetes 集群上部署。

图 7-3. Anomalo 架构如何与典型部署中的所有其他系统集成的简化示例。
从底部开始,用户通过 Web 前端或 API 客户端与平台交互,通过企业身份提供商(IdP)的单点登录(SSO)集成和 API 密钥进行安全保护。Web 前端提供了丰富的图形用户界面,用于通过浏览器与平台进行交互,并通过 HTTPS 与 Web 服务器通信。
Web 服务器通过 HTTPS 响应来自 SSO、API 或浏览器会话的所有外部请求。然后,后端控制器创建作业,这些作业排队并计划执行。有一个动态工作池可以接手这些作业并处理它们(这些作业可以是元数据检索任务、SQL 查询、检查逻辑或机器学习作业)。
所有这些内部系统在内部数据库中维护共享状态(我们使用 Postgres)。该数据库本身可以托管在环境内(如 Docker 或 Kubernetes 中),也可以是像 AWS RDS 这样的托管 Postgres 服务。
大部分操作发生在执行检查的工作者中。这些工作者将向外部通道(例如 Slack、Microsoft Teams、PagerDuty)发送通知,并从正在监控的数据仓库、数据湖或数据库中读取数据(例如 Snowflake、Databricks、BigQuery、Amazon Redshift)。
他们还会将处理的大型对象,例如记录级数据的样本或生成的可视化内容,写入云对象存储(如 AWS S3)。在典型的部署中,这是客户控制的文件存储桶。
当任何工作者遇到运行时错误时,它们会将有关异常的信息写入像 Sentry 这样的外部平台,用于调试异常(不包括任何客户数据)。
最后,整个平台可以自动升级。控制器监视 Anomalo 容器注册表,以寻找标记为特定客户或环境的新部署,然后以安全可靠的方式自动升级所有内部组件。
安全性
或许不用说,但我们还是说一下:当您与业务数据源集成时,您承担了保护数据的重大责任,这些数据可能包含个人身份信息(PII)和其他敏感信息。根据您的使用情况,您可能需要遵守围绕数据处理的特定合规和法律要求(请参阅我们的数据处理协议示例)。
在为第三方客户开发解决方案时,应该考虑与数据安全相关的里程碑。 SOC 2 认证是存储客户数据在云中的服务提供商的行业标准。由AICPA开发的 SOC 2 是一种广泛的审计程序,确保公司安全地处理客户数据,并保护组织及其客户隐私。
在多个数据仓库之间进行数据对账
当您的组织利用多种数据存储解决方案时,通常在多个位置表示重复数据,并希望在两个表中确保数据在迁移前后是相同的。一个例子是在迁移前后确保数据的一致性。
监控以确保数据的一致性通常采用两种形式:基于规则的测试或无监督机器学习。
使用基于规则的测试比较数据集
如果两个数据仓库中的两个表完全相同,则必须满足三个条件:
-
架构是相同的。表必须具有相同的列,相同的类型,以相同的顺序排列。
-
主键集是相同的。表的行必须在主键上一对一连接。
-
每一行具有相同的值。在主键连接时,两个表的行中的值必须相同。
如果这三个条件都成立,则两个表必须完全相同。在两者之间,没有已添加、重复、丢失或修改的数据。
然而,基于规则的测试方法要求数据位于同一个数据仓库中,以便能够在规模上评估表之间的连接。这对于非常大的数据集来说是不实际的,并且引入了因 ETL 过程中将数据移动到同一数据仓库平台中的问题而导致的假阳性风险。
使用无监督机器学习比较数据集
在第四章中,我们讨论了无监督机器学习方法如何用于按需比较两个数据集的数据质量监控。在这种情况下,您将从各自的数据仓库中的表中抽取数据样本,然后训练模型来预测数据是来自仓库 A 还是仓库 B。通过使用 SHAP 值解释模型的预测,您可以精确定位和根本原因样本数据中的差异。
尽管这种方法可能无法像规则那样捕捉每个行级问题,但它适用于大规模数据集,并允许您比较来自不同源数据仓库的数据,而无需进行任何 ETL 过程。
比较摘要统计信息
比较两个表的最终方法是计算每个表的一些摘要统计信息,然后比较这些统计信息以确保它们是相同的。例如,您可以计算按产品类别分组的行数和平均价格,以比较产品价格列表数据是否在不同环境之间一致地复制。这种方法具有很好的可伸缩性,并允许您确保某些小方面的数据是相同的。但是,如果表很大,它无法比较表中的所有记录。
实际上,我们发现后两种方法的组合——在聚合时确保行数和一些关键统计信息相同,并确保在绘制样本时使用 ML 没有显著的分布差异——是跨平台数据集对账的最可扩展和可靠的方法。
数据编排器
不同的业务用户希望在不同的位置查看或执行数据质量检查。在某些情况下,他们希望在数据传输和转换过程中进行数据质量检查——换句话说,在数据进入您的数据仓库的“静止”状态之前。有时候,他们甚至希望在数据进入数据仓库之前就执行数据质量检查。
这就是编排器和 ETL 工具如 Apache Airflow、dbt、Fivetran、Databricks Workflows 或 Prefect 的作用所在。
与编排器集成
与编排或工作流工具集成的标准模式是创建作业,允许您的监控解决方案插入数据编排 DAG。简单地说,DAG 是一系列按特定顺序完成的任务,具有上游和下游依赖关系。
一个常见的 DAG 是首先从适当的源中提取数据,例如用户日志和分级环境。这些可能是启动 DAG 的独立任务,如图 7-4 所示。完成这两个任务后,可以合并和转换数据到所需的格式,最后加载到存储的适当位置。编排工具自动化和调度此过程,提供在特定任务完成或失败时的可见性。
通过将您的监控平台与编排工具集成,您可以在 DAG 的几乎任何时刻运行检查。例如,您可能希望在转换阶段之后或数据提取阶段之后(或两者都)运行检查。

图 7-4. 一个包含数据质量检查的数据编排 DAG 示例,在发布数据之前。
我们建议您至少支持三种类型的功能:
运行检查
连接到您的监控解决方案,并运行已配置为表的检查。在图 7-4 中,这是AnomaloRunCheck。
作业传感器
您需要一种方法来确定监控系统何时完成运行检查。我们通过轮询方法来实现此目的。在图 7-4 中,这是AnomaloJobComplete。
校验检查
这使用户可以决定他们是否关心所有检查是否通过,还是仅有些检查通过。一旦我们获得检查的输出,我们可以确保如果未通过任何“必须通过”检查,我们会引发异常,停止工作流的完成并触发向用户的通知。在图 7-4 中,这一步是AnomaloPassFail。
通常,将此功能打包到 ETL 工具的库中对用户非常有用。这些功能背后的代码并不特别复杂。这里是一个用于运行检查的 Airflow 运算符示例:
# Importing BaseOperator for creating custom operators in Airflow.
from airflow.operators import BaseOperator
# Importing AnomaloHook to interact with Anomalo API.
from anomalo import AnomaloHook
class AnomaloRunCheckOperator(BaseOperator):
def __init__(self,
table_name,
anomalo_conn_id="anomalo_default",
*args,
**kwargs):
super().__init__(*args, **kwargs)
self.anomalo_conn_id = anomalo_conn_id
self.table_name = table_name
def execute(self, context):
# Creating an API client.
api_client = AnomaloHook(
anomalo_conn_id=self.anomalo_conn_id
).get_client()
# Fetching the table_id corresponding to the table name.
table_id = api_client.get_table_information(
table_name=self.table_name
)["id"]
# Triggering the run checks operation in Anomalo and getting job ID.
run = api_client.run_checks(table_id=table_id)
# Logging the information about the triggered checks.
self.log.info(f"Triggered Anomalo checks for {self.table_name}")
# Returning the job ID for the triggered run.
return run["run_checks_job_id"]
AnomaloRunCheckOperator触发一个作业,运行给定表中的所有检查。table_name是 Anomalo 中表的完整名称,anomalo_conn_id是连接到平台的连接 ID。
接下来,我们将演示如何设置一个示例 Airflow DAG,该 DAG 摄取数据,然后使用AnomaloRunCheckOperator对其运行检查。
我们首先导入定义 DAG 所需的 Airflow 模块和类,以及自定义的 Anomalo 运算符和传感器:
from airflow.models import DAG
from airflow.operators.empty import EmptyOperator
from airflow.utils.dates import days_ago
from airflow.providers.anomalo.operators.anomalo import (
AnomaloPassFailOperator,
AnomaloRunCheckOperator,
)
from airflow.providers.anomalo.sensors.anomalo import AnomaloJobCompleteSensor
接下来,我们为 DAG 任务定义默认参数,并设置 DAG 的基本参数:
# Default arguments for DAG tasks.
args = {
"owner": "AL",
"start_date": days_ago(1),
}
# Define the DAG using context manager.
with DAG(
dag_id="AnomaloDAG", # Unique identifier for the DAG.
default_args=args, # Default task arguments.
description="Simple Anomalo Airflow operator example", # DAG description.
schedule_interval="@daily", # Frequency of DAG execution.
) as dag:
DAG 包括多个任务。有ingest_transform_data,这是将数据引入并对其进行一些操作的初始任务。完成后,我们希望有一个任务可以使用AnomaloRunCheckOperator在表格上运行检查。请注意,以下步骤均缩进,因为它们发生在 Airflow DAG 上下文管理器内部:
# Initial task to ingest and transform data.
ingest_transform_data = EmptyOperator(task_id="ingest_transform_data")
# Task to run checks on a specific table using AnomaloRunCheckOperator.
anomalo_run = AnomaloRunCheckOperator(
task_id="AnomaloRunCheck",
table_name="public-bq.crypto_bitcoin.outputs",
)
正如之前讨论的,我们希望在 Anomalo 作业完成之前轮询,并使用anomalo_sensor任务完成这一操作:
anomalo_sensor = AnomaloJobCompleteSensor(
task_id="AnomaloJobCompleteSensor",
# Reference to the previous task's job ID.
xcom_job_id_task=anomalo_run.task_id,
poke_interval=60,
timeout=900, # 15 minutes
mode="poke",
)
工作完成后,我们将运行一个任务来验证各种数据质量检查,并最终发布数据:
anomalo_validate = AnomaloPassFailOperator(
task_id="AnomaloPassFail",
table_name="public-bq.crypto_bitcoin.outputs",
must_pass=[
"data_freshness",
"data_volume",
"metric",
"rule",
"missing_data",
"anomaly",
],
)
publish_data = EmptyOperator(task_id="publish_data")
定义好这些任务后,只需设置任务依赖关系来形成 DAG:
(
ingest_transform_data
>> anomalo_run
>> anomalo_sensor
>> anomalo_validate
>> publish_data
)
数据目录
由于今天许多企业正在处理大量不同类型的数据集,数据目录正成为数据从业者工具箱中越来越重要的一部分。数据目录提供了数据资产、元数据和关系的集中视图,使组织更容易发现、理解和使用数据。例如 Alation、Databricks Unity Catalog、DataHub 和 Atlan。
数据目录与数据质量工具之间的集成是自然而然的发展——企业意识到了理解其数据和确保数据高质量是相互关联的目标。这两个步骤都可以视为数据治理的一部分,它是一个框架,用于定义组织中管理数据资产的政策、流程和标准。它确保数据得到适当的访问、保护和信任,以满足组织及其利益相关者的需求。
作为进一步促进数据质量工具与数据目录之间连接的示例,Alation 在 2022 年推出了开放数据质量倡议,提供“开放的 DQ API、开发者文档、入门、集成最佳实践和共同营销支持”。他们在目录中添加了一个数据质量标签(参见图 7-5),数据质量系统可以通过 API 推送信息。

图 7-5。作为他们的开放数据质量倡议的一部分,Alation 添加了显示数据质量检查的钩子。查看此图的完整版本,请访问https://oreil.ly/adqm_7_5。
目录与数据质量监控之间的集成可以是双向的。在目录内部,能够直接看到与表格相关的数据质量信息非常有帮助,而无需切换上下文。或者,从监控平台内部,深入到目录中也可以很有用,以探索表格使用情况和元数据。
在目录内显示详细的数据质量信息(参见 图 7-6)有几个重要的原因。数据目录通常是企业探索数据集的主要工具,可能有助于特定用例,例如开发新的分析仪表板。在此阶段,分析师可能正在从数百个他们一无所知的表格中进行选择。重要的是了解给定表中的数据是否良好:它是有效和已批准的,还是从未经过测试?在分析师的指尖提供数据质量详细信息可以确保企业基于可信赖的信息做出决策。

图 7-6. 数据质量检查显示在表的目录概述中,任何问题都会在 UI 中标记。
此外,数据目录的一个任务不仅是整理资产,还要告诉企业哪些资产最受欢迎和常用。通过将数据质量信息整合到目录中,可以快速看到哪些受欢迎的表格实际上已验证。如果管理者正在推动改进数据质量的倡议,这对于确定投资资源的优先级非常有帮助。总体而言,它作为企业是否依赖可信赖数据的一个评估标准。
与目录集成
与数据目录的基本集成包括标记表格是否完全设置了检查或监控,显示数据质量检查结果在目录中,并深度链接到监控平台获取更多信息。
然而,随着目录增加对数据质量工具的增强支持,更先进的集成正在变得可能。例如,如果您的监控工具提供了额外的可视化功能(例如根本原因分析),您可能考虑将其整合到目录中。
通常,与数据目录集成遵循一个发布模型,数据质量监视器将汇总其结果并发布到目录拥有的指定位置。集成主要基于 API,因此拥有安全且企业级准备的 API 非常重要。
例如,您可以提供一个返回监控结果的 REST API,格式为 JSON。端点可能包括:
GET /get_checks_for_table
返回给定表格 ID 的当前配置检查/验证的列表。
POST /run_checks
在给定表格上手动运行所有或部分检查。
GET /get_run_results
获取单次运行的执行检查结果。
对于 GET /get_run_results 调用,检查你可能需要提供的元数据包括:
-
检查 ID:特定数据检查的标识符
-
检查运行 ID:检查运行实例的标识符
-
完成时间:检查运行完成的时间
-
创建元数据:关于谁何时创建检查的信息
-
最后编辑的元数据:关于最后编辑的信息,包括时间和编辑者
-
错误状态:检查是否遇到错误
-
评估消息:详细描述检查评估情况的文本
-
异常详细信息:任何异常的消息和回溯信息
-
历史上下文:检查随时间推移的表现摘要
-
样本数据:用于良好和坏数据样本的 SQL 查询和 URL
-
结果统计:与检查相关的定量指标及其名称
-
成功标志:指示检查成功或失败的布尔值
-
检查配置:包括类型、描述和优先级级别
-
分类状态:在分类工作流中的当前状态
在我们的经验中,集成最棘手的部分是正确匹配表 ID,因为表名并不总是一个完美的标识符(它们在不同的数据目录中可能会有稍微不同的表示),而且每个企业的环境都会有所不同。
您还需要考虑安排问题:您希望多频繁地将结果推送到目录和/或从目录中获取更新?作为第一步,您可以使用脚本运行更新,最终将调度程序集成到您的平台中,以便每天或在其他某种节奏上自动化这个过程。
数据消费者
尽管仍处于初期阶段,数据质量集成的另一个强大领域——并且可能变得更受欢迎——是消费数据的应用程序,如 BI 和分析工具以及 MLOps 平台。
分析和 BI 工具
像 Tableau 这样的分析工具,因为它作为数据使用的目的地,是显示数据质量监控信息的好选择,例如数据集是否已验证为高质量。实际上,Tableau 有几个数据质量 API,比如一个用于添加数据质量警告的 API。如果您使用 BI 仪表板来跟踪关键绩效指标,请考虑将此度量监控与您的数据质量工具同步,以便您可以轻松地找到根本数据漂移的原因。
数据驱动的组织通常会遇到业务指标定义不一致的问题。例如,业务的一部分可能会将view_count定义为不包括非常短的视图,比如持续时间少于 10 毫秒的视图,而另一组可能会包括所有视图,这看起来像是数据质量问题,但实际上只是缺乏一致性。
我们一直对 dbt 如何通过推出 dbt 指标和 dbt 语义层来解决这个问题感兴趣。这使得组织能够在 dbt 中集中定义关键的业务指标,如收入、客户数量和流失率。数据质量监控工具可以成为 dbt“指标就绪集成”,并使用 dbt 指标定义。例如,如果您的工具监视关键绩效指标,可以自动接收在 dbt 中定义的指标。
MLOps
如果您的公司正在使用像 Amazon SageMaker 这样的 MLOps 平台,很可能已经内置了某种模型监控水平。然而,大多数平台监控的指标通常是模型性能、延迟和可用性,而不是数据流入模型时更难检测到的问题,导致预测结果不佳。通过将数据质量监控与 MLOps 工具集成,您可以构建一个系统,当模型需要重新训练时,警告数据科学家底层数据已发生漂移,或者存在像数据中的 NULL 值这样的错误可能导致模型行为不稳定。
图 7-7 是从 Google Cloud 架构中心调整过的示例 MLOps 架构图。

图 7-7. 示例 MLOps 架构图(来源于“MLOps: Continuous Delivery and Automation Pipelines in Machine Learning”,Cloud Architecture Center,https://oreil.ly/rfAmt)。
这种复杂的流程旨在自动化 ML 系统的持续集成、交付和训练。以下是您可能希望引入数据质量监控的几个关键点:
源数据
源数据通常来自云数据仓库或数据湖,被转换为模型的信号,然后存储在特征存储中。监控这些数据非常重要,因为这是训练 ML 模型的入口点。
特征存储
特征存储可能已在您的数据仓库中复制,这是您希望监控的另一组表。如 第三章 所讨论的,特别是要查找 NULL 值百分比的变化、分布偏移和相关性变化。这些任何一个都可能表明特征计算不正确,或者模型可能遇到会导致意外行为的冲击。
训练数据
训练数据从特征存储中批量获取。使用数据质量监控来比较当前训练快照与先前的训练数据集或生产数据可能会有所帮助。如果训练数据的分布突然发生变化,您可能会面临一些模型风险。
模型性能
在训练的模型评估步骤中,您可以记录训练和推断时间、测试集性能和特征重要性分数等数据。模型监控理想情况下已集成到您的 MLOps 工具包中,但如果这些指标在您的数据仓库中可用,数据质量平台也可以监控这些指标。
特征服务
当您的模型在线并进行预测时,获取预测时的特征、记录它们,并与最新训练运行使用的特征值进行比较,这是非常有价值的。这可以告诉您在训练和实际数据之间是否存在显著差异,这意味着您的模型在生产环境中可能表现不佳。
预测和业务逻辑
虽然您可以直接监控机器学习模型的预测,但我们认为监控由这些预测驱动的业务逻辑更为重要。例如,您是否突然将大量交易标记为欺诈?这可能表明外部数据中存在真实的趋势,但也可能意味着您的模型由于数据质量问题而表现不稳定。
结论
当您在大规模自动化数据质量监控时,您可以创建验证数据质量(或否)的方法。通知是解决数据质量问题的主要方式,但要真正让您组织内的用户与系统互动,并在公司整体上关注数据质量,您需要超越通知,并将监控的信息和信号整合到整个数据工作流程中。在本章中,我们为您提供了这样做的工具。
第八章:在规模上操作你的解决方案
在这最后一章中,我们将讨论当你将自动化数据质量监控解决方案投入运行并长期维护时可能面临的挑战。我们将重点放在清晰定义问题上,让你的用例和需求指引你选择适合团队的方法。
操作自动化数据质量监控这样的技术解决方案遵循一般模式。首先是获取平台的过程,可以是自建也可以是从第三方购买。然后是初始配置和启用,以便您的团队能够成功使用平台的所有功能。一旦一切都运行良好,“最终”阶段是持续使用平台来促进组织的目标——在这种情况下,是长期改善和维护数据质量。我们按照这些阶段的顺序构建了这一章节。现在,让我们深入了解如何达到数据质量卓越的稳定状态。
自建还是购买
一旦组织全面了解到他们正在面临的问题,并研究了解决方案空间中的选项,他们就需要做出决策:是自建还是购买?
建设并不一定意味着从头开始建设,而且很少如此。小团队可能采取的常见策略是围绕基于规则的数据质量评估的开源软件包(如 Great Expectations 或 Deequ)构建自己的平台。完全控制数据质量计划的路线图有其优势:
-
你将能够为你最关心的指标调整你的 ML 模型。
-
你可以从用户体验的角度设计通知和可视化。
-
如果你已经为管理数据构建了其他内部系统,比如定制数据目录,那么使你的 DIY 数据质量监控平台与这些系统兼容可能比与供应商集成更容易。
-
你将完全控制优化成本、运行时间和平台的其他性能特征。
-
你可以构建你需要的功能,包括供应商可能不提供的定制功能。
-
你不会为任何不必要的东西付费。
另一方面,DIY 方法的缺点通常会阻止企业选择这条路线,即使他们拥有庞大的工程团队:
-
你需要从业务的核心竞争力中分出时间,专注于构建由复杂的 ML 模型驱动的复杂平台。这通常包括聘请有才华的工程师和数据科学家,他们可能对构建新的耀眼事物感兴趣,但不太愿意留下来维护它。
-
大型企业的不同团队可能会使用不同的技术构建自己的定制解决方案。要整合这些并在组织的不同部分具有相同的数据质量透明度会很困难。
-
您的团队将负责平台的全天候支持和维护,以及培训和引入新用户。
-
数据环境不断变化。为了跟上步伐,您需要随时间推进您的平台创新,增加新功能并迭代您的模型。
-
供应商专注于优化数据质量监控平台的性能和成本,这是他们业务的核心。除非您的工程师经验丰富且积极主动,否则可能会得到次优的指标。
-
通常,自制系统只会生成未被采纳的电子邮件。除了检测数据质量问题外,您需要设计一个复杂的用户体验界面,包括可视化,以使通知可操作,并帮助根本原因分析。这往往是业务意识到项目太复杂无法内部解决的时候。
随着数据质量监控的供应商生态系统的发展,对于那些尚未专注于构建数据平台的企业来说,购买选项变得越来越有吸引力。总体运营成本通常低于企业自行开发和维护的成本。通过供应商,企业可以立即开始提升数据质量,而不必等待内部平台的建设完成,后者通常需要一年或更长时间。
云数据仓库越来越多地为企业添加数据质量监控功能。这是有道理的,您应该评估它们提供的内容与您的首选供应商之间的差异。请记住,数据仓库和数据湖并不专注于数据质量监控,因此可能没有动力在这一问题上进行创新,提供最佳用户体验或解决边缘案例的需求。
这里许多团队额外关注的问题是锁定。他们可能使用多个数据仓库/数据湖,并且不希望为了数据质量而需在多个地方查阅数据。或者如果他们想后期迁移数据,他们关心在新平台上重现所有规则、检查、通知和流程的切换成本。
供应商部署模型
企业对外部供应商的主要关注点之一是安全性和数据隐私。因此,关注供应商的部署模型至关重要,因为这将极大影响数据的保护程度。一般有三种部署选项(某些供应商可能只提供其中一种或几种),它们在平台安全性和控制方面有很大的差异。
SaaS
使用供应商进行数据质量监控的最简单方法是采用 SaaS 部署。这可能就像在公司网站上注册,添加信用卡支付,并输入您希望用于访问云数据仓库的凭据一样简单。
然而,SaaS 部署模型引入了严重的安全和隐私风险。SaaS 平台需要对您希望监控的数据具有无限制的读取访问权限。即使解决方案仅使用摘要统计信息来检测数据质量问题,也需要数据样本来帮助找出问题的根本原因。此外,许多组织担心分享其仓库的元数据,因为表和列名可能提供战略或竞争情报,这些情报并非公开。对于大型组织来说,这种暴露通常是不能接受的。
完全在 VPC 内或本地部署
与 SaaS 相对的是完全在虚拟私有云(in-VPC)或本地部署(on-prem)的监控解决方案部署,这意味着整个监控应用运行在由客户控制的安全云端或本地环境内。
像 Docker 和 Kubernetes 这样的新技术使得管理和扩展这些在 VPC 内部部署比过去更加容易。升级仍然可以自动进行,客户无需参与。例如,可以将新版本发布到带有标签的 Docker 注册表,指示适合哪些客户。然后,应用内运行的自动化服务将查找部署的新标签并自动升级部署。有关更多详细信息,请参考图 7-3。
完全在 VPC 内或本地环境可以配置为一系列安全姿态:
允许或禁止远程访问
允许供应商远程访问部署通常对客户有利,可以提供更高质量的支持并协助解决任何配置或问题。然而,如果数据仓库中存储了特别敏感的数据,则可能无法实现(或者可能需要承包商关系)。
没有任何信息的出口
最敏感的客户可能希望阻止所有数据离开部署。这意味着一切;例如,供应商将无法从系统获取异常报告或任何遥测数据。这可能会显著增加客户的监控和维护负担,以及供应商所需的部署或支持费用。
大多数企业和关注安全和隐私的客户选择完全在 VPC 内部部署。值得注意的是,从管理角度来看,in-VPC 是一个更复杂的选择 —— 如果您的组织不习惯管理这种部署方式,可能会在起步阶段遇到学习曲线。但对许多公司来说,投入时间和资源来完全控制数据和元数据存储和处理的位置是值得的。完全在 VPC 内部部署是确保这种控制的唯一方法。
混合
在 SaaS 和完全在 VPC 之间的极端之间,还有第三条路。混合解决方案试图通过将查询和数据分析层放置在客户环境内(在 VPC 中),而将展示和用户交互层保留在供应商的云中(SaaS),来结合 SaaS 和在 VPC 中的优点。
然而,考虑到数据质量监控的性质,这与 SaaS 并没有太大不同。客户的数据仍然经常会离开他们的环境。为了工具提供重要的透明度和数据质量问题周围的上下文,需要向用户展示数据的汇总统计和样本。并且元数据也需要被暴露,即使只是描述用户在界面中检查的表格和列。
在实践中,我们发现混合解决方案必须在以下两种方式之间做出妥协:要么削弱用户体验,要么面临将敏感数据暴露到客户环境之外的风险。
表 8-1 展示了这些部署模型。
表 8-1. 供应商部署模型
| 部署模型 | 查询和数据分析层 | 展示和用户交互层 | 部署复杂性 | 您的数据可以暴露给供应商吗? |
|---|---|---|---|---|
| SaaS | 在他们的环境中 | 在他们的环境中 | 最简单 | 是 |
| Hybrid | 在你的环境中 | 在他们的环境中 | 一些复杂性 | 是 |
| 完全在 VPC 中 | 在你的环境中 | 在你的环境中 | 最复杂 | 否 |
配置
与任何复杂的技术解决方案一样,你构建或购买的数据质量监控平台可能会有一系列需要在初始化时指定的选项。如果你处理大量数据,像是监控哪些表格以及在这些表格中检查哪些数据这样的配置决策尤为重要。你在这里的决定可以保护你免受飙升的数据仓库成本或供应商费用的影响,并确保你的解决方案即使对于有数十亿记录的表格也能继续良好运行。
在考虑到这些问题的情况下,我们将详细讨论大多数企业在设置他们的解决方案时遇到的问题:
-
如何确定哪些表格最重要
-
如何决定监控表格中的具体数据
-
如何避免手动配置所有内容
确定哪些表格最重要
虽然可以仅使用表格元数据实施整个数据仓库的广泛可观测性,但是查询实际数据值的自动化检查需要更多的计算资源来运行。因此,通常最好确定哪些表格最重要,并仅为这些表格配置“深度”数据质量监控(请参见表 3-1,这是很多公司如何进行这种分解的示例)。从最重要的数据开始也将有助于更快地接纳团队成员,并在扩展工具使用之前建立信任。
如何识别这些关键表格呢?对于较小的组织来说,数据团队可能很明显地知道哪些表格最重要。对于大型组织来说,这种知识可能分散在整个组织中,并且随着时间的推移,收集和维护变得更加困难。通常情况下,对表格中数据质量最关心的人是这些数据的消费者。一个能够让那些对某个表格拥有最深专业知识的人员轻松设置监控的工具,将增强组织在决定监控哪些表格时的灵活性。
你可能还想查看来自数据仓库的 SQL 查询日志。通过这种方式,你可以确定哪些表格(以及列和段)被自动化系统、临时分析师查询或商业智能报告平台最频繁地查询。这种“热度”是最重要数据的一个很好的代理。
决定监控表格中的哪些数据
对于大表格(特别是数十亿行),经常监控整个表格可能会非常昂贵。为了保持解决方案具有成本效益,你的平台应该只监控最近的数据。如果你总是仅查询最近一段时间的数据(通常昨天的数据就足够了,尽管有时需要更高的频率),你的监控将大大减少对底层数据仓库的负载,从而节省资金和运行时间。
在大多数情况下,如果仅监控最近的数据,你仍然可以覆盖到大多数导致数据质量问题的原因,因为这些问题通常只发生在最新进入表格的数据中。当然,也有例外情况,例如当历史数据被就地更新时,这些表格需要不同的监控策略,如在“就地更新表格”中讨论的那样。
要监控最新的数据,你需要按时间对数据进行分区。虽然这听起来可能很简单,但在某些情况下,由于数据仓库的要求或数据的来源,可能会变得相当复杂。想要了解我们遇到的许多不同时间分区方案的小样例,请参见图 4-3。
另一个复杂情况:有些表格可能没有可以用来识别“最近”记录的时间列。在这种情况下,除了让自动化监控系统在每次更新时检查整个表格并建立数据快照以比较表格随时间变化外,没有其他选择。
大规模配置
如果你有 10,000 张表格,逐一通过界面手动配置显然不合理。此外,你可能有数百或数千个现有的自定义数据质量规则和检查(例如在 dbt 中),你可能希望将它们迁移到你的新自动化平台上。
This is another reason, alongside those mentioned in Chapter 6, that your data quality solution should include a robust API with hooks to configure tables for monitoring and add, delete, or update custom checks programmatically. A CLI can be particularly helpful here, as well as the ability to specify configurations via YAML files.
When configurations are specified programmatically, they can be maintained in a version control system like Git. For critical data, this may be helpful for auditing purposes or for ensuring checks are reviewed and approved through a code-review process before being applied to production.
That said, you can’t expect to lock down and control all configurations programmatically. You’ll need to also allow users to make adjustments and add checks to tables as needed, including business users who may not be comfortable with writing code. So, we suggest that you provide two options: configuration by code as well as self-service configuration via a UI.
Enablement
Both during and after your initial configuration, you’ll be introducing your monitoring platform to many different types of stakeholders and, most likely, multiple teams as well. The more people who use the tool, the more people will be invested in improving data quality at your organization. This is a great thing, but it comes with the challenges of managing a large, diverse user base. In this section, we’ll describe best practices you can implement for a successful enablement.
User Roles and Permissions
Different systems will have different roles and permissions for their software. For example, a vendor solution might have admins who can fully configure tables, down to viewers who can only look at the results of data quality checks.
It’s best to define these roles and permissions very early on. Who will be given the admin roles, and will there be a backup if they go on leave? Will each team have its own admin, or will one person be responsible for all of the configuration? What role will new users get by default when they join a team? If someone has a problem with access, how do they escalate this?
Additionally, you may want to think about whether different teams or divisions within an organization should be siloed in terms of what tables they can access in your tool. It’s safest to give access only to what a user needs. For example, not all users will need access to sensitive tables containing HR information.
Onboarding, Training, and Support
推出数据质量监控平台到您的组织需要仔细考虑和规划,有许多不同的路径可以选择。例如,您可以使数据质量成为一个从顶层向下的倡议,立即在数十个团队中推广。另一方面,您可以从小处着手,专注于让一个或两个团队成功,并通过早期成功推动全组织的病毒式采纳。我们看到这两种方法都奏效了——正确的选择取决于您的文化、您的需求紧急程度、您拥有的资源数量以及团队之间的紧密联系程度。
不论细节如何,我们看到以下一般策略帮助企业引入新员工团体、培训他们成功,并确保长期支持用户:
初始启动和需求收集
即使在推出之前,也应该举行一个启动会议,包括数据工程、数据科学和将受到平台影响的业务用户等利益相关者。理想情况下,您已经在与出席者中实现了数据质量监控的认同,但这也是一个团结您的团队并将其与业务成果联系起来的地方。这也是您应该分享入职计划和时间表、听取关注和愿望清单以及展示平台演示的阶段。
现场培训会议
在启动后,通常会计划在接下来的几周内安排一到三次现场培训会议。会议通常与各个团队对应,因为您业务中的每个组织可能具有非常不同的使用案例和要求。您应该邀请那些将积极使用工具的员工,特别是那些涉及配置和设置的员工。根据您的构建与购买决策,建设和管理平台的供应商或内部团队将主持这些会议。(如果与供应商合作,随着时间的推移,您可能会积累足够的内部经验,从而能够自行进行培训。)
有时,现场培训会伴随内部工作会议,根据需要帮助团队整合所学内容,并就适合他们具体需求的数据质量监控检查和配置达成一致。
随需课程
尤其对于拥有许多团队需要引入的大型公司而言,随需培训课程非常有帮助,这可能是一些书面教程和视频演示的结合,以适应不同的学习风格。这使用户可以按自己的节奏进行学习,并为难以通过现场培训扩展的主题提供额外的资源。
办公时间
在入职阶段及其后,许多团队发现有可能参加与供应商/负责内部团队每周办公时间的选项很有帮助。这使用户能够与熟悉数据质量监控平台的专家面对面讨论任何问题。为了促进学习,这些讨论可以记录并分享。
持续支持
无论是来自维护平台的内部团队还是外部供应商,都应该有人负责持续支持。这可能包括一个专门的 Slack 频道,用于直接访问平台专家,以及定期会议来审查平台路线图和功能更新(定期发布说明也应向用户提供)。支持平台的人员应建立错误、性能和基础设施问题的监控,并针对解决的 SLA 设定目标(例如,在一小时内解决 P1 问题)。
入职、培训和支持最终不仅仅是减少摩擦的一种方式;它们是提高你组织中与数据质量相关的参与度的方法。它们帮助宣传平台并在内部传播,识别出可能根本不是最初需求评估的相关团队,并利用监控解决方案的机会。上述最佳实践也有助于缓解人们悄悄失败并放弃尝试使用工具的常见问题。
随着时间的推移提高数据质量
最终,您投资于数据质量监控,因为您希望提高组织中的数据质量。虽然拥有一个优秀的数据质量监控平台是一个起点,但这并不是全部。有一些策略可以确保您的组织持续改进并创建一个从一开始就真正投资于数据质量的文化。
计划
您需要确定并致力于超越任何单一工具或界面的数据健康计划,并改变与数据工作的方式。
例如:
-
进行第三方数据源的审计。你的企业正在使用哪些?哪些正在被监视?
-
投资于与您的数据质量监控工具集成的额外数据基础设施,例如数据目录。
-
创建文档,例如运行手册,用于调试问题。这减少了只存在于某个团队或个人之间的信息孤岛问题(当人们更换团队或离开公司时,信息会丢失)。
-
确保每张表都有明确的负责人和清晰的通知渠道以及分类处理过程,如第六章中描述的。
-
开发数据生产者和数据消费者之间的合同,以明确数据方面的期望(例如,什么构成了延迟交付,或者数据更新时通知谁)。
我们发现,投资于数据质量监控本身通常会在组织中建立数据健康的动力,就像首次投资健康一样,比如承诺定期锻炼,可能会启动各种相关的变化,比如改善更加营养的饮食。
指标
当您投资于提高数据质量时,您很可能会对衡量进展的方式感兴趣。这对于许多不同的原因都很重要,无论是帮助鼓励其他团队使用您的工具,还是向高级领导展示影响。
分类和解决方案
成功的最重要指标之一不仅是检测到的数据质量问题数量,还有这些问题的严重程度以及解决它们的速度。致力于分类和解决问题将决定监控投资的回报价值的成败。
为此,建立一个清晰的流程来处理检测到的数据质量问题以及持续改进和迭代这一流程至关重要。在数据质量问题的响应时间上建立 SLA,并确保清晰地在团队之间进行沟通。
高管仪表板
高级领导通常从数据质量平台的高层指标仪表板中受益。这可能包括仓库覆盖率水平,每周检测到问题数量的趋势,或者问题最多的表格。有关更多仪表板可视化和详细信息,请参考第三章。
评分卡
跟踪数据质量倡议进展的另一种方式是为每个表格提供一个数据质量评分卡,将表格健康的不同方面结合成单一值、百分比或等级。
例如,为了汇编一个表格的评分卡,每次在该表格上运行数据质量监控时,您可以为通过的检查给予积分,并扣除未通过的检查的积分。您可能希望为每个数据质量检查分配一个权重,因为并非所有检查都同等重要。一种做法是使用检查的优先级水平(高、普通或低,参见第六章),因此高优先级的检查对表格的整体数据质量评分影响最大。
评分卡提供了对表格数据质量的一览,并允许您快速比较表格。当表格可以链接到组织信息时,评分卡成为了了解哪些团队、业务部门或数据仓库正在提高数据质量,哪些正在落后的一种方式。因为这些原因,评分卡不仅在监控平台内非常有效,而且在与数据目录等其他系统集成时也同样如此。
在制定评分卡时,您通常需要做出艰难的产品和用户体验决策。例如,您可能会决定将数据质量分数分为解释表格需要改进的类别,例如在图 8-1 中。然而,定义哪些类别以及如何将检查分类到这些类别中的决定远非简单。

图 8-1. 一个数据质量评分卡的示例,其中分数分配在四个类别中,并随时间跟踪。
在实践中,评分卡很少是一刀切的。至少,数据质量平台应提供 API 或数据导出功能,允许组织提取构建此类评分卡所需的数据。例如,每次检查运行的历史记录,以及检查的优先级和相关标签,以及检查是否通过或失败,可以作为简单评分卡的基础。这些数据还可以与组织已有的其他数据合并,用于构建他们自己的定制数据治理仪表盘。
从混乱到清晰
![OpenAI. (2023). ChatGPT(2023 年 9 月 25 日版本)[大型语言模型]。 https://chat.openai.com](assets/adqm_08in01.png)
OpenAI. (2023). ChatGPT(2023 年 9 月 25 日版本)[大型语言模型]。https://chat.openai.com
现在您已经掌握了解决运营挑战的工具,您将为改变公司数据质量的故事迈出坚实的一步。
我们很高兴您在本书中花时间学习如何实现大规模自动化数据质量监控。总结一下,这段旅程带领我们走过了:
第一章
为什么数据质量很重要以及错误如何影响您的业务
第二章
一个综合的数据质量解决方案的外观,以及为什么这必须超越基于规则的测试,包括与机器学习的自动化集成
第三章
如何评估您的业务从这样的解决方案中获得的投资回报率
第四章
一种利用机器学习实现大规模自动化数据质量监控的算法
第五章
调整和测试您的模型,确保其在实际数据中表现良好
第六章
如何实施通知并避免常见的过度警报问题
第七章
为何以及如何将您的监控与其他数据工具和系统集成
第八章
部署您的解决方案,接纳用户,并持续改善数据质量
如今许多企业在没有足够质量控制的情况下运营数据工厂。传统方法未能应对现代企业每天处理的大量数据。幸运的是,随着数据堆栈的其余部分现代化,数据质量监控也在不断发展。正如本书所述,利用机器学习自动化数据质量监控是一种强大的解决方案,可以积极地检测和解释潜藏在最重要数据中的问题,影响到机器学习模型、BI 仪表盘,最终影响到推动底线的决策。
在本书中,我们开放地分享了许多内容,包括杰里米在 Anomalo 刚刚起步时希望知道的事情,因为我们相信数据质量的民主化。我们希望更多与数据打交道的人,无论是从事问题解决的从业者,还是对在不稳定基础上建设感到担忧的高级管理层,都能知道有一条前进的道路。这是一条通向更高士气、更好商业成果的道路,让你能够信任公司依赖的数据。现在,你已经准备好迈出下一步了。
附录:数据质量问题的类型
本附录提供了关于现实世界中常见的数据质量问题类型的额外信息。这个列表对于评估您正在构建或购买的数据质量监控解决方案非常有帮助。最终,您将希望为组织中每个重要数据集的每种问题类型确定并解决策略。
对于每个数据质量问题,我们将提供一个示例,常见原因的总结,这些问题通常如何影响分析(使用数据和人类进行决策)和机器学习(使用数据和算法自动化流程),以及我们对如何最佳监控数据源这些问题的建议。

图 A-1. 分成四类别的数据质量问题 (DALL-E 3)
如图 A-1 所示,我们已将本附录中的问题分成四个广泛的类别,显示出问题影响数据的级别。
-
表格问题
影响整个表的问题,并不限于单个行或值:
数据迟到
当数据迟到并且在系统需要数据时不能及时提供给消费系统时
模式变更
当数据结构发生变化,比如新增或删除列,列名变更,列的数据类型变更,或者半结构化列中的 JSON 模式变更时
无法追踪的变更
当表中的记录以无法事后审计的方式进行就地更新时
-
行问题
影响表中整行数据的问题:
不完整的行
当数据到达,但应该存在的行数只有一部分存在时,通常是数据的某个特定部分缺失
重复行
当同一行数据在数据中出现多次,而实际上只打算出现一次时
时间上的不一致性
当相关数据记录的时间或顺序存在差异或不一致时
-
数值问题
影响数据特定值或单元格的问题:
缺失值
当数据集中某列的数值未填充,而是显示为 NULL、零、空字符串或其他代表缺失数据的标志值时
不正确的值
当某列的数值不正确,可能是记录级别的编码问题,或者结构性错误导致某些或所有记录被错误表示时
无效值
当数值未能符合指定格式、约束或业务规则时
-
多重问题
多表关系问题:
关系失败
当两个数据源之间的关系完整性失败,导致某些记录的重复或缺失连接时
不一致的来源
当时间或不同数据源的数据值存在差异时,本应相同的数据。
请注意,这些问题不一定是独立的,因为其中一些可能既是潜在问题的原因,也是其症状,因此它们可能同时发生。例如,源表可能迟到,导致数据转换中的关系失败,并在事实表中缺少数据。
我们尽可能详尽地列出了这些问题。但请注意,我们明确排除了语义问题,这可能涵盖数据在技术上是正确的,但被用户误解的情况,以及可访问性问题,其中数据虽然正确,但无法访问。这两者都是可以通过数据目录和访问控制平台解决的重要数据治理问题。
表问题
迟到到达
定义
数据迟到,并且在系统需要数据时,消费系统无法获取数据。
例子
将 web 应用程序事件日志从 S3 移动到数据仓库的系统停止处理新的日志记录,因此分析师登录查看关于用户行为的仪表板时,最近一天没有事件数据。
原因
-
上游没有生成任何数据,可能是捕获点(日志未工作)或上游系统或第三方的处理故障或中断。
-
负责将数据加载到数据仓库的系统出现问题,可能是因为中断或处理数据时遇到严重异常。
-
负责数据转换的系统出现问题,可能是因为中断或应用转换逻辑时发生严重失败(例如,在数据仓库中的 SQL 查询开始抛出异常)。
-
生产数据的管道因上游其他数据质量问题而停止发布;迟到的数据意味着向最终用户提示当前周期的数据尚未准备好供使用。
分析影响
-
当数据延迟时,仪表板通常会显示异常——可能有可视化图表无法渲染,或在仪表板上显示错误,或显示 NULL 或 0 值。
-
用户通常会意识到数据丢失,并稍后返回查看仪表板。如果这种情况经常发生,用户会开始对数据的可用性失去信心,并寻找其他来源或在没有数据的情况下做出决策。
-
操作用例(例如分析当前营销活动或当前站点行为)将受到最近周期的迟到数据的不成比例影响。
ML 影响
-
模型训练。通常不会受到影响,因为模型训练通常是基于长时间的数据历史进行。
-
模型推断。 迟到的数据通常会导致 ML 特征为 NULL 或 0,而不是应该有的有意义值。或者,迟到的数据可能意味着 ML 模型正在使用已过时的数据。在这两种情况下,这会引入偏差到 ML 模型中,可能导致预测大幅变化。
如何监控
-
一种方法是使用表观测监控。按照定期时间表,收集表最后更新的元数据。然后建立时间序列模型来预测下一次更新应何时到达,并在更新延迟时发出警报。然而,这可能会忽略表正在原地更新但新记录仍未到达的情况;也可能忽略表被删除并替换但没有新记录的情况。
-
最健壮的方法是查询数据最新时间分区的可用性。观察随时间记录到达所需的时间,然后再次建立时间序列模型来预测记录应该到达的时间(或日期),并在未发生时发出警报。
-
注意,除了使用时间序列模型外,您还可以设置表应何时更新或数据应何时到达的硬性 SLA。这在您需要数据按指定时间到达的用户或系统的情况下非常有利。但请注意,这在大规模情况下将很难维护。
模式变更
定义
数据的结构变更,如新增或删除列、列名称更改、列数据类型更改或半结构化列中 JSON 架构的更改。
示例
某列名称令人困惑,因此工程团队决定将其重命名以使其更清晰。然而,下游数据处理系统依赖于该列名称,并且也没有进行更改,导致数据处理失败(数据延迟或不完整)或数据丢失。
原因
-
这些变更的根本原因几乎总是有意为之,旨在扩展、优化或重构运行时捕获的数据。
-
生产应用程序的数据框架(例如 Django)具有确保这些变更在整个应用程序中传播的强大机制(所谓的“迁移”),但这不会扩展到摄取这些应用程序发出的数据的系统中,必须手动考虑。
-
JSON 格式数据因其灵活性而受到重视,可以捕获新数据而无需在当前系统或下游应用程序中进行迁移。然而,任何依赖该 JSON 数据结构的下游应用程序可能会受到这些变更的影响。这些变更通常更频繁且监管不严。
分析影响
-
简单来说,模式变更将使列不可用,并且仅仅破坏依赖它们的仪表板。
-
在更复杂的情况下,模式变更是看起来缺失数据或分布变更的根本原因,因此表现为这种方式。
ML 影响
-
模型训练。当模式发生变化时,适当地回填历史数据可能是不可能的(例如,如果新信息正在被捕捉或类型以有损方式发生变化)。在这些情况下,机器学习模型将因为其数据随时间不一致而变得不那么强大。
-
模型推断。如果发生模式更改,并且模型尚未重新训练以适应这些更改,那么模型可能会失败(因为数据不符合预测的正确格式或形状),或者可能进行狂野的预测,因为更改后的数据被强制转换为 NULL 或其他标志值或填充值。
如何监控
-
可以使用验证规则明确说明给定表的模式应该是什么。然而,长时间内保持这种验证非常困难。
-
一种更自动化的方法是在某个固定的节奏下对模式数据进行快照(我们在 Anomalo 每天都这样做),并自动检测不良变化,例如列被删除或重命名。
不可追溯的变化
定义
表中的记录以不可追溯的方式直接更新,无法在事后审计。
示例
一个数字广告公司只存储其广告活动的当前状态。广告活动通常会延长,但原始结束日期没有历史记录,因为它们不断被覆盖。基于预计广告活动结束日期的报告是不可靠的。虽然广告活动的开始日期不应更改,但它们也可能被覆盖。在运行期间,广告活动还可以更名。当分析师日复一日地生成报告时,他们的数字不匹配,无法追溯到原因。
原因
-
维度数据通常会被直接更新以显示客户或位置的当前状态。位置的属性可能会更改,例如它是否开放或暂时关闭,或者客户可以在不同州份有新地址。如果不跟踪这些更改的时间,基于当前维度表版本的历史报告可能是不正确的。
-
客户交易或索赔数据可能会在原地更新,当交易开始时创建一个初始记录。各种字段最初将作为 NULL 值,因为它们是未知的(例如最终发货日期或索赔金额)。然后,随着这些事件的逐渐了解,记录会被更新。这导致数据始终具有更多最近记录的 NULL 值。
-
数据管道可以“重新运行”,以纠正错误和之前确定的问题,而不保留不正确数据的记录以进行比较。
-
表格可能具有数据架构,整个表格每天被截断和重新加载,掩盖了哪些记录实际上发生了更改。
-
注意,一些数据仓库支持“时间旅行”的概念,以便在最近的某个时间点上查看表的历史。这可以帮助缓解这些问题的影响,但支持通常仅限于非常近期的时间段,并且可能难以扩展到用于机器学习应用程序的记录级时间旅行。
分析影响
-
在这些表上进行的数据分析就像建立在流动沙上一样,因为连续两天运行相同的查询不会提供相同的结果。分析师无法重建导致前一天运行的条件。
-
数据段的度量可能由于维度数据的变化,在报告中显示出从一天到下一天不一致的值,导致分析师对数据失去信任。
-
由于分析师无法重建过去的世界,历史分析变得不可能。
-
随时间计算的度量可能因为最近数据不完整而显示出突然的尖锐变动,而较早的记录已经完成更新。
机器学习影响
-
模型训练。 在原地更新数据而不保留完整的更改审计日志会消除可能对 ML 模型有价值的大量信息信号。
最糟糕的情况是,对历史数据的更新会“泄漏”关于模型试图预测的响应的信息。例如,如果每次下订单时都更新客户表,则此数据不能用于预测客户将来是否会再次下订单。如果是这样,那么最近的更改(或更完整的记录)的存在将是一个非常强烈的信号,表明客户在过去有过购买行为。但这不会推广到未来的预测中。
-
模型推断。 模型通常是在完全成熟的历史数据(所有原地更新已完成)上训练的。这是可以接受的,但前提是模型随后将用于预测同样完全成熟的数据。实际上,这很少发生,模型将用于仍然不完整的数据,并且模型的结果将非常偏向。
如何监控
-
可靠地检测这个问题的唯一方法是比较从给定表中随时间抽取的数据摘要统计或样本,用于特定一组记录。这组记录可以是随机选择的主键集,或者可以是使用 SQL WHERE 子句指定的特定时间窗口,查询日期或数据的时间分区。
-
然后,您可以监控随时间推移行数的漂移(数据随时间原地删除或添加),或者关键统计数据的漂移,如数据质量或业务指标。
-
一个更健壮的方法是反复从给定时间分区的数据中取样,并使用机器学习来检测数据分布漂移的差异。这可以自动识别在原地更新的特定列和数据段。
行问题
不完整的行
定义
数据到达,但应该存在的行数只有一小部分。通常缺少特定数据段。
例子
给定某一天数据的所有记录已经到达,除了一个国家的记录,由于该国家的第三方正在发生故障而延迟处理。
原因
-
可能通过不同的过程或供应商收集不同分段的数据。例如,来自不同区域的数据来自不同的云可用区。或者使用不同的工具收集不同类型的事件。
-
就分段单独收集或处理数据而言,通常会发生仅有一个或少数几个分段捕获、传输或加载数据失败或延迟的情况,而不是所有分段。
分析影响
-
对于数据中评估的任何指标,缺失的分段可能高于或低于该指标的平均水平,这将相应地使指标出现偏差。例如,如果 Android 事件中的交易收入较低,并且这些事件丢失,则整体交易收入将高于预期。
-
当指标以这种方式出现偏差时,可能导致团队得出错误的结论。例如,任何最近的业务变更可能会“怪罪”导致的指标变化。
-
导致数据不完整的分段越小,诊断不完整性根本原因就越困难。如本文所述的偏见指标可能会成为新常态。
-
一旦问题被识别出来,可能无法对不完整的数据进行补填,从而在数据中留下永久的伤痕。
-
仪表板显示指标的分段细分可能出现问题,因为某个特定分段突然在仪表板上消失,导致团队忽视仪表板作为可靠的真实数据来源。
ML 影响
-
模型训练。 在罕见情况下,数据的某个分段可能会长时间丢失而未被检测到。在这些情况下,数据将缺失于训练数据集中,模型将无法学习如何处理该数据段。然后,当模型用于预测来自该数据段的记录时,它们可能会非常不可靠。
-
模型推理。 如果在预测时未处理某个分段的记录,则这些预测将无法供业务使用。这可能导致消费者的默认非个性化行为,或者决策系统转为基于规则的行为,所有这些都将表现不佳。
如何监控
-
表观察方法可用于监控不完整的行;然而,由于使用了元数据,它们只能检测表的整体行数变化,并不像对于特定时间分区添加的行数变化那样敏感。
-
更稳健的方法是使用 SQL 查询和表中的分区时间列来计算时间分区(天或小时)的行数。然后,您可以使用时间序列模型检测表行数中是否有意外下降。
-
无监督的 ML 模型非常擅长检测数据中是否存在某个特定分段已消失或比预期少得多的情况。
-
对于数据的非常高基数部分(例如,商店 POS 系统),通过连接到包含所有商店的维度表,明确确认所有商店是否已包含可能是必要的。
重复行
定义
当数据行被意外加载多次时,同一行在数据中出现多次,而实际上只有意出现一次。
例子
信用卡支付交易数据集与每种支付交易类型的元数据参考表连接。这个参考数据集是手动在 Excel 中维护的,并且在有更改时偶尔会被删除和重新加载。因错误添加了一个支付类型两次而不是直接编辑。这些数据被加载,现在该类型的所有信用支付交易都与两条参考记录连接,导致数千个交易在下游重复。
原因
-
如信用卡例子所示,单个表中引入一个重复记录的微小变化,可能在数据连接到其他表后扩散成大量重复。因此,重复数据往往会扩散,如果连接到自身(例如,匹配一些行或与其他表),可能会呈指数级扩展。
-
重复的一个常见原因是同一记录被多次加载到数据仓库中。当系统加载数据时出现故障,并且数据工程师必须手动恢复加载操作时,就可能发生这种情况。同一个文件或其部分可能会被无意中加载两次。
-
重复数据还可能源自分布式系统中的日志记录。这些系统通常能够容忍单个节点的故障,并且通常保证任务“至少执行一次”。然而,这意味着由于分布式系统中的通信问题,它们有可能运行多次。结果可能是重复记录(可能具有不同的时间戳)。
分析影响
-
重复数据往往会导致分析结果夸大——记录计数会高于预期,基于总和的统计数据也会如此。这可能会使企业的绩效看起来更好,或者对你正在聚合的任何实体有过高评价。
-
重复数据还会对任何平均统计数据产生偏差,因为重复的记录在比较时将有效地获得更大的权重。
ML 影响
-
模型训练。
-
当数据在训练数据中随机重复(这种情况很少见)时,它不太可能对模型结果产生实质性偏差。事实上,许多算法使用随机抽样行,这些行不会受随机重复数据的影响。
-
然而,如果重复数据存在偏差,那么模型将学会更多地关注这些重复记录。在极端情况下,它将会记住它们(因为它们出现得如此频繁),并且对其预测具有不合理的高置信度。
-
最糟糕(也是最常见)的情况是,在进行训练和测试拆分之前,数据重复。这将导致一些记录同时出现在训练数据和测试数据中(因为它们出现两次,这在一定程度上是可能的)。这种从训练数据到测试数据的记录“泄漏”将导致对模型性能的无效估计。这可能会导致训练模型选择了与数据不匹配的模型,在生产中的表现远远不如开发模型时的表现。
-
-
模型推理。
-
推理时间的重复数据对机器学习模型本身并不构成问题。然而,无论哪个系统消费模型的预测,都必须处理重复的记录。
-
这通常意味着决策系统会尝试为同一实体多次做出相同的决策。这可能导致重复发送电子邮件、重复发放优惠券、重复创建贷款申请等问题。
-
如何监控
-
可以通过创建一个验证规则来检测重复行,该规则确保数据在主键列上是唯一的,或者在定义主键的一组列上是唯一的。但是,这需要专家测试并为每个感兴趣的表定义这个规则。
-
更可扩展的方法是自动识别那些随时间一直是唯一的列,并在任何这些列中出现意外重复值时进行警报。
时间不一致性
定义
相关数据记录的时间或顺序存在差异或不一致。
示例
营销团队正在分析用户首次访问网站时所采取的步骤序列。跟踪的关键事件包括用户首次访问的第一个页面、创建帐户时、首次将商品添加到购物车时以及首次完成交易时。然而,与添加商品到购物车相关的某个分布式系统正在经历性能下降,因此积累了长时间的购物车添加日志队列。所捕获的时间戳是记录日志时的时刻,而不是商品在用户浏览器中被添加的时刻。结果是,有时第一次添加的商品会出现在第一次完成交易之后。分析将这些记录排除为无效记录,并减少了已添加商品到购物车的用户完成交易的计算百分比。
原因
-
这些问题最常见的原因是事件的时间戳要么不正确,要么使用错误的时间戳(如上例中,我们使用的是记录的时间戳,而不是客户端事件的时间戳)。
-
这些问题的另一个非常常见的原因是,同一张表中不同列使用不同时区的“墙上时间”存储。例如,记录更新的时间戳存储在协调世界时(UTC)中,而交易时间存储在发生交易的本地时间中。
-
这类时间问题也常常会因 SQL 逻辑错误而悄悄潜入数据的下游转换。例如,分析工程师可能会错误地获取用户在第一次会话中将商品添加到购物车的最大时间,而不是最小时间。对于在其首次会话中进行多次交易的用户来说,这也会导致添加到购物车的时间晚于交易时间。
分析影响
-
当事件的时间顺序不准确时,计算事件发生所需时间的结果就会出现偏差。这可能导致对关键活动完成所需时间的估算出现分析错误。俗话说,时间就是金钱,因此这些不准确性可能导致次优甚至价值破坏的决策。
-
在某些情况下,事件顺序可能会变得不可能(用户结账而未将任何商品添加到购物车中)。如果移除这些不可能的记录,则结果会因其缺失而出现偏差。
-
如果包括它们,可能会产生极端后果。例如,我们曾看到由于时间戳转换问题导致事件被预定到遥远的未来。当这些事件的时间计算并与其他时间平均后,可能会完全混淆计算并导致不合理的结论。
ML 影响
-
模型训练.
-
事件发生所需的时间可能是机器学习模型的非常重要的信号(客户完成动作所需的时间或内部流程所需的时间)。这些不准确性往往会使模型误以为这些事件比实际重要性低。
-
更为棘手的情况是,当事件本身成为你试图预测的内容的一部分时。例如,如果你正在预测交付需要多长时间,而这一度量受到不正确时间数据的偏倚,那么整个模型可能会受到偏倚,并且在实际应用中表现不佳。
-
-
模型推断**. 在预测时,这些时间上的不一致将表现为错误的数值,这会对其他类型的字符串或数值数据一样产生不利影响。
如何监控
-
可以创建复杂的验证规则,通过表自连接,计算事件之间的顺序或到达时间间隔,然后设置明确的保护措施来保证事件顺序或到达时间的顺序性。
-
无监督机器学习算法可以检测到这些问题的一些表现形式,只要数据被重塑为每个实体或交易一行,具有多列事件和时间戳序列。算法将能够学习这些列之间的关系,并识别是否存在意外的变化。
值问题
缺失值
定义
数据集中某列的数值未填充,而是出现了 NULL、零、空字符串或其他标志性值,表示数据缺失。
示例
在一个汽车保险数据集中,每个保险政策都有一列显示被保险车辆的车门数量。这列数据为空(例如,对于摩托车而言车门无关紧要),但突然之间出现了更多的空值,因为一个第三方车辆信息源不完整,导致左连接失败,引入了本应具有车门数量的车辆的空值。在数据库中,NULL 可能会成为一个重载概念:它可以表示值不适用(摩托车没有车门)、未知(车辆类型尚未确定)或缺失(已知车辆但车门数量字段尚未填充)。
原因
-
缺失数据可能出现在事件捕获的数据收集点上(例如,记录被写入),但对事件的测量(例如,事件的背景或关键结果)未被捕获。
-
数据移动时,缺失数据也可能会渗入数据中,例如,如果数据加载到的系统期望替代数据类型,那么值可能会被强制转换为新数据类型,无法强制转换的值可能会变成缺失数据。
-
缺失数据通常也会通过左连接引入。例如,当一组交易左连接到一个维度表时,如果连接键在维度表中不存在,那么从维度表到交易的任何数据都将缺失这些键的数据。
-
缺失数据也可能积累,从而导致在粒度级别上的少量缺失数据在聚合级别上变成更大的缺失数据比例。例如,在某些平台上,如果计算包含缺失值的列的总和,则总和的结果可能是缺失的。因此,一个在交易级别上只有 1%缺失的数据集,在按客户、产品或地理位置聚合时,可能会变成 10%或 50%的缺失数据。
分析影响
-
缺失数据常常会导致分析结果出现偏差。最常见的处理方法是将缺失数据从分析中移除。如果数据是随机缺失的,那么结果将会更加嘈杂。
-
但是,大多数数据不会随机缺失;它们缺失是有具体原因的。通常缺失的记录与数据集的其他部分相关联,这些部分可能在任何分析指标下具有显著更高或更低的数值。这将导致分析中的向下或向上偏差,这可能会影响决策。
ML 影响
-
模型训练。
-
缺失的原始数据通常会转化为缺失或默认值(如 0)增加的 ML 特征。
-
在某些情况下,由于只能应用于少量观测值,某个特征对模型的重要性会大大降低。这将限制模型的能力,因为它无法像应该学习的那样多地从这个特征中学习。
-
在极端情况下,缺失数据可能与响应结果相关联,这是由于引入缺失数据的方式所导致的特殊情况。例如,SQL bug 导致某个字段仅在用户流失时变为缺失。然后,将此字段用于模型预测流失将会误导模型认为缺失数据导致了流失。这将使得模型在预测时非常不可靠。
-
最后,缺失数据可能会出现在响应本身中(我们不知道我们试图预测的结果)。这将导致该数据在建模过程中被完全删除,这将限制模型的强度并使其在以前具有此缺失模式的记录的未来任何预测上产生偏差。
-
-
模型推理。
-
在预测时,当模型接收到其不期望的缺失数据时,这些缺失值可能会导致模型完全无法进行预测,从而停止系统的正常运行。为了避免这种情况,缺失值通常被强制转换为数值(通常为 0),如果该值在训练数据中不经常出现或者出现在非常不同的情况下,可能会导致极其不准确的预测。
-
在其他情况下,模型可以优雅地处理缺失值(例如,基于树的模型可以在该特征上进行分割整合),但如果缺失的原因与训练数据中的缺失方式不同,预测结果仍然会存在偏差。
-
如何监控
-
可以使用验证规则检测数据是否缺失,并使用指标监控缺失数据的百分比。然而,这两者都需要进行大量的维护和细心处理。
-
无监督机器学习在检测数据突然缺失方面非常有效。
不正确的值
定义
由于记录级别的错误编码问题或结构错误误代表了部分或所有记录,某一列中的值是不正确的。
示例
社交媒体平台正在追踪执行特定操作的用户百分比(例如,喜欢、分享或回复内容)。应用程序代码标记具体操作,并为了更精细地分析用户行为,应用程序将一个标签分成两个,以捕捉某些行为的更细微差别(例如,“分享”现在变成“带评论分享”或“直接分享”)。然而,这种变更并未明确告知所有下游用户,因此一些查询寻找旧的聚合标签开始在最近的数据周期中返回零记录。
原因
-
最明显的不正确数值的原因是在数据录入点处错误捕获数据,通常是人类在表单中输入数据时,而表单上又没有足够的控制。例如,用户可能输入一个无效或错误的地址。总体而言,随着现代应用程序中输入验证方法的改善,这些问题变得越来越少见。然而,系统之间仍可能存在差异,主数据管理(MDM)工具可用于管理和协调这类信息。
-
更系统性的不正确值的原因是生成数据的系统(应用程序或第三方)在生成、记录或处理数据的方式上进行了变更,从而影响了特定记录的值。过去以特定字符串值表示的记录现在可能有新的字符串值,或者它们的数值发生了与被测量数量无关的变化。
-
在某些情况下,这些变更是误导数据的“错误”,可以在上游系统中修复。但在其他情况下,它们是有意的变更,可能是为了改进数据的细化程度或单位。例如,财务交易金额可能从美元变为欧元。或者产品尺寸可能从英寸测量变为厘米。
-
不正确的值也可能由于数据处理方式的变更而进入数据集。例如,SQL 可能用于在数据仓库内转换数据集。该 SQL 需要定期更改,以适应输入数据的新特性、SQL 输出的新要求,或者适应其他上游变更。每次 SQL 的更改都可能引入无效值的风险,例如在
CASE WHEN语句中犯错误,错误地重新分类字符串值。
分析影响
-
当个别记录的值编码不正确时,对分析影响不大,因为分析通常使用聚合数据。然而,当大量值不正确时,基于该数据的统计或可视化可能会严重偏倚。
-
例如,许多分析查询将严格专注于数据的片段,并使用
WHERESQL 子句将计算缩小到行的子集。当数值不正确时,这些 SQL 查询将完全错过数据,或者将其包含在不应包含的地方。这可能导致量和统计数据大幅变化,因为这些子集与通常情况下的不同(通常如此)。 -
当数值不正确时,所有这些数值的分析计算也会有本质上的错误。计算总和、均值或其他统计量都会因错误编码引入的记录百分比和方差量而存在偏差。
ML 影响
-
模型训练。
-
当数值无效时,ML 模型仍会尝试学习无效值与其试图预测的结果之间的关系。在最好的情况下,这种关系不存在,数据只是没有像它本应有的那样有用,因此模型的性能将低于其本应有的水平(可能导致误报或漏报)。
-
但是如果变量很重要,那么无效值几乎肯定会影响模型在结果和数据之间学习的关系。这可能导致模型将值与不真实的结果相关联。一旦数据质量问题得到解决,模型将开始表现得非常不稳定。
-
-
模型推理。
-
每当模型遇到不正确的数值时,都会影响模型的预测。预测的幅度取决于受影响数据在模型中的重要性(在进行预测时数据被赋予的“权重”),以及数据编码中的错误幅度(这里的幅度实际上是指受影响记录的预测差异有多大)。
-
在实践中,这可以从可忽略的(浮点精度的微小变化可能不会产生实质影响,或者对模型预测不重要的类别的错误编码可能不会有影响)到完全破坏受影响记录的预测,导致极端错误的决策。
-
如何监控
-
验证规则可以编码用户对给定列中的值类型的期望,考虑到列中的其他数据,但这需要极大的谨慎和维护。
-
时间序列模型可以用来监测列中每个常见值的可用记录的百分比,并且可以检测是否存在意外的漂移。然而,这种方法最好只用于重要表中少数几个关键列,并且不能处理具有数值、时间或其他高基数值的列。
-
无监督机器学习模型非常擅长检测由不正确值引起的数据分布意外变化,尤其是这些变化影响了大量行。
无效值
定义
值未符合指定格式、约束或业务规则。
示例
一个客户信息的主机系统以 YYYYMMDD 字符串格式导出日期。这些数据被加载到 Snowflake 中,其中市场活动被配置为根据客户的出生日期发送电子邮件。在主机系统进行配置更改后,现在日期以 DDMMYYYY 格式导出。在 Snowflake 中,这导致出生日期远在过去,导致用户的年龄范围永远不会被选择用于市场活动,从而导致营销活动和新客户获取显著下降。
原因
-
许多数据格式问题在数据提取和加载的早期阶段就被捕获,因为数据类型与加载到表中期望的数据类型不一致。例如,字符串格式的整数在加载到期望日期格式为数值类型的表时会报错。
-
但是,在列的格式约束内,值的格式仍可能与用户或下游系统预期的格式不一致。这在字符串列中最为常见,除了需要有效的字符集和可能有长度限制之外,很少强制执行其他类型的规则。在 JSON 或其他嵌套数据中出现格式不正确也很常见(有关更多信息,请参见第三章)。
-
格式问题最常见于捕获或记录数据的系统发生更改时,导致格式突然改变。例如,第三方可能决定开始以(XXX) XXX-XXXX 格式而不是 XXX-XXX-XXXX 格式表示美国电话号码。
-
在其他情况下,格式问题是由于同一企业内部对格式的标准不一致而引起的。当数据分别在每个组织中存储和处理时,这些不一致可能并不重要。但一旦数据汇总到单一的数据仓库或数据湖中,这些格式问题就会对数据使用者造成严重影响。
-
最后,可能存在不符合企业现有约束条件的无效数据。例如,可能不可能存在负货币交易(公司向客户购买产品)。在这些情况下,问题更多是数据本身不正确,而且比其他不正确的值更为明显,因为这些值本身是不允许的。
分析影响
-
不正确或不一致的格式化数据会显著拖累分析团队,因为他们必须在想要以一致的方式联接、合并或聚合数据时纠正这些格式问题。这可能需要临时处理,大大减慢了生成分析和洞察的时间。
-
在其他情况下,当数据无效时,效果与其他无效数据相同,只是对最终用户更加显而易见。
ML impact
-
模型训练。
-
高基数的字符串数据通常不直接用作 ML 模型的输入,除非它们在对数据进行自然语言处理时,这在许多情况下可以对格式变化具有弹性。
-
然而,如果在这些数据上进行特征工程处理,格式不一致的数据会损害模型在训练时对不同格式数据段的泛化能力。通常情况下,进行特征工程的工程师会发现这一点,就像分析团队一样,他们只需多做一些工作来克服这个问题。
-
-
模型推断。
- 当字符串列的格式意外改变时,从该列计算的特征也可能会改变,这将导致 ML 模型出现突然的反应,并导致预测表现不稳定。
如何监控
-
可以使用验证规则找到无效值,主题专家会表达数据预期格式。
-
无监督机器学习可以检测值格式的变化,特别是如果它可以使用字符串值的模式识别作为 ML 模型的输入。
-
无效值经常导致下游 SQL 由于类型转换问题而报错,这使得直接监控它们变得困难;使用
TRY_CAST的验证规则可以帮助明确捕捉这些错误,特别是在表的上游形式上,其中所有列类型都被视为变体。
多问题
关系失败
Definition
两个数据源之间的关系完整性对一些记录失败,导致重复或缺失的连接。
示例
一家电商公司希望分析哪些营销渠道推动了最多的订单量。一个包含营销归因数据的表与另一个包含客户订单信息的表进行左连接。然而,由于上游日志记录问题,所有首次使用安卓设备进行互动的客户的归因数据均丢失。结果是许多订单被丢弃,且所有结果均不包含安卓数据。
Causes
-
关系失败的最常见原因实际上是其他数据质量问题——要连接的其中一张表中的数据要么缺失要么重复,导致连接失败或者每个连接键产生的记录数比预期值多或少。
-
关系失败的一个更微妙的原因是使用的标识符本身具有数据质量问题,这可能是不兼容的格式或不正确的值。例如,为了保护用户的隐私,用户的电子邮件地址可能会被哈希为字母数字字符串,但仍然提供了一种一致的用户标识方法。如果一个源开始使用与其他源不同的哈希算法,那么连接将彻底失败。
-
最后,在某些情况下,连接逻辑上是不正确的。例如,如果两个表在一个月的日期列上进行连接,但一个源使用的是日历日期,而另一个源使用的是银行工作日日期,连接将失败(每个月的日历天数多于银行工作日,因此记录将丢失)。
分析影响
- 关系失败的净结果通常是不完整的行(记录被丢弃),缺失的值(左连接导致 NULL 值),或重复的行(连接不是一对一,因此有导致行数激增的笛卡尔连接)。对分析的影响与这些其他数据质量问题的影响相同。
ML 影响
-
模型训练。 其影响将根据连接失败的净影响而异(请参见“不完整行”,“缺失值”或“重复行”部分)。
-
模型推断。 其影响将根据连接失败的净影响而异(请参见“不完整行”,“缺失值”或“重复行”部分)。
如何监控
-
可以使用表达预期的连接语义的验证规则来监视对这些连接语义的遵守(至少一个记录,恰好一个记录,或多个记录作为连接的结果)。
-
在其他情况下,这些问题可以通过无监督的 ML 模型捕获,这些模型应用于具有关系问题的表或视图的结果。
不一致的来源
定义
时间或数据源之间的数据值差异应当是相同的,但实际上存在差异。
例子
在一个源关系数据库内,将复杂的财务数据转换、连接、聚合和汇总,以生成内部财务指标。相同的原始数据被导出到云数据仓库,然后经过类似的转换和聚合,生成应当完全相同的报告,这些报告将分发给管理层和投资者。然而,在基于源关系数据构建的内部工具和数据仓库生成的外部报告之间存在关键财务数据的差异。
原因
-
当相同的数据以不同的方式处理,或通过不同的系统处理时,可能会在一个数据处理路径中引入数据质量问题,而另一个路径则不存在这些问题。这可能表现为管道末端产生的聚合数据存在差异。
-
也可能存在逻辑上的不一致性,这是通过不同语言编写的代码、不同团队编写的代码或同一团队在不同时间编写的代码引入的。这些不一致性最终将显示在数据本身中。
分析影响
-
当应该相同的数据不一致时,通常意味着两个数据集中的一个或两个质量较差。我们讨论过的任何其他数据质量问题都可能出现在原始、中间或最终数据集中。这些问题将导致基于这些数据的任何分析中产生错误的决策和无效的洞察。
-
在某些情况下,不一致可能太小,对决策没有实质性影响。然而,这些不一致通常会降低最终用户对数据的信任,因为他们将手动尝试调和个别统计数据,并且如果发现差异,会质疑数据的完整性或处理过程。
ML 影响
-
模型训练. 最大的 ML 影响是在构建模型的训练数据与推断时使用的数据不一致时。这通常发生在 ML 工程师使用存储在数据仓库或数据湖中的历史数据构建训练数据集时。当将基于该数据构建的模型投入生产时,它可能会接收来自源系统的实时数据。这些数据可能与最初用于训练的原始数据不一致,这可能导致模型在生产中表现非常糟糕。
-
模型推断. 请参阅上面关于模型训练的答案,因为这里的主要问题是训练和推断中使用的数据不一致。
如何监控
-
可以使用验证规则为每个表格计算汇总统计信息,并在不同来源之间比较这些汇总统计信息。这些统计信息也可以按时间或业务部门进行分段。
-
无监督 ML 也可以用来比较从两个来源抽取的随机记录样本,并总结值的分布和关系的差异。
-
最后,你可以逐个比较两个来源之间的记录,但这通常非常消耗计算资源,因为每个记录必须从每个来源移动到第三平台,然后在内存中比较记录。这还需要为每个来源识别一个主键,以便能够有效地将记录连接在一起。
-
最后但并非最不重要的是,如果您能以确定性方式对数据进行排序,那么您可以计算数据的加密哈希值,并比较这些哈希值。然而,这也是非常耗费计算资源的,而且不能清楚地显示出差异的具体位置或其重要性。这些数值本身也必须完全相同,并以相同的方式转换为字符串值,这在不同平台之间是非常具有挑战性的。


浙公网安备 33010602011771号