到目前为止,我们已经讨论了事务型数据与分析型数据、事务型数据库与分析型数据库以及数据湖与数据仓库等的各种区别。了解这些区别有助于我们准确掌握数据可能存储的位置。我们还了解了数据管道中不同存储格式和步骤的各种优势和风险。但具体到数据质量,我们应该特别考虑哪些指标呢?
接下来我们将讨论什么是数据质量指标,如何提取它们,以及如何知道自己是否在正确利用它们。
你无法修复你无法测量的东西。同样,如果没有数据质量指标,你就无法获得数据质量。这些数据质量指标可能是关键绩效指标(KPI)或者其他表明你的数据足够健康和可靠的指标。
我们建议根据数据宕机的时间(也就是你的数据不完整、有错误、出现缺失或者其他不准确的时间段)来度量数据质量。如前所述,我们将其称为“宕机时间”,以便追溯到互联网的早期时代。那时,在线应用程序是一个“有则更好”的选择,如果它们暂时挂掉了,那也没什么大不了的。你可以接受宕机时间,因为企业并不会过度依赖它们。而现在,我们已经进入互联网时代至少20年了,而在线应用程序对于几乎所有企业来说都是至关重要的。所以,公司会仔细度量宕机时间,并投入大量资源来避免发生服务中断的情况。
同样,公司也越来越依赖利用数据来进行日常运营并做出关键决策。但是我们还没有按照数据宕机所要求的程度来对它进行处理。虽然少数公司正在制定服务级别协议,以便让数据团队对数据的准确性和可靠性负责,但这还并不是常态。未来几年,我们预计人们将对数据宕机进行更严格的审查,并更加注重将其影响降至最低。
在评估数据是否有问题时,你可能会建立一个问题列表:
· 数据是最新的吗?
· 数据是完整的吗?
· 字段是否在预期的范围内?
· 空值率是否高于或低于应有的水平?
· 模式是否已经更改?
这个列表对你的数据质量要求来说可能还不够全面,但它仍然是一个好的开始。它让我们从回答一个泛泛的困难问题(“我的数据是否有问题?”)转变到一系列更具体的问题。我们正朝着数据质量指标迈进,它应该用定量且可度量的结果来回答上述问题。
上述问题的答案来自对特定数据资产的分析,这些资产主要以我们前面讨论的形式出现,例如数据仓库、数据湖以及它们之间的转换层等。
我们要如何从数据仓库的环境中制定数据质量指标呢?回顾2.3.1节,数据仓库是通过其结构化内容和“写时模式”架构来进行区分的。
可扩展性
跟踪大量的表和大数据集可能会非常棘手。你需要考虑批量调用、针对不同规模来优化查询、去除重复数据、对各种模式进行规范化,并将所有这些信息存入可扩展的存储库中,以便理解这些信息。你需要构建一个专用的数据管道,以便能够随着时间的推移操作、更新和维护该管道。
不要忘记跟踪你的Snowflake信用消费情况(你可不想接到CFO的电话)。
监控栈的其他部分
构建真正可靠的数据管道并实现数据可观测性需要的远不只是收集指标这么简单。随着现代数据栈的发展,密切关注实时流数据、数据湖、仪表板、机器学习模型和其他数据资产的可靠性正变得至关重要。
随着数据栈的增长,监控数据质量指标以纳入其他技术和数据源是一项基本挑战。由于数据可能会在管道中的任何地方中断,因此你需要通过一种方法,不仅从数据仓库中而且还要从其他数据资产中来提取指标和元数据。
无论是数据工程师、分析工程师、机器学习团队还是数据科学家,投资于能够让这些数据资产相互配合的解决方案都应该是重中之重。真正的数据可观测性( https://oreil.ly/Zbtj3 )扩展到数据仓库之外,提供对数据湖、ETL、商业智能仪表板中数据健康状况的观察,以免错误的数据像滚雪球一样演变成更大的问题。
下面,我们将重点介绍如何从Snowflake中提取数据质量指标来度量数据仓库中数据的健康状况。虽然我们在此特定示例中使用Snowflake,但从Redshift、BigQuery和其他常见的基于OLAP的数据仓库中提取数据质量信息也都遵循类似的过程。
示例:从Snowflake中提取数据质量指标
Snowflake是最流行的云数据仓库工具之一,其设计从一开始就优先考虑了数据质量和数据完整性。在构建更可靠的数据管道时,数据仓库最重要的功能之一就是能够直接从其中提取数据质量指标并将其可视化以便进行简单的分析,如图2-2所示。
图2-2:在Snowflake中提取数据质量指标有助于在给定时间点呈现数据仓库中的数据健康状况
以下是从Snowflake中成功收集数据质量指标所需采取的四个步骤。
第1步:映射清单。 我们假设你在Snowflake上有一个名为ANALYTICS的数据库(尽管与大多数数据栈一样,这种情况很少发生)。要在你的环境中运行以下查询,只需将ANALYTICS替换为你要跟踪的数据库的名称即可。若要列出账户中的所有数据库,你可以运行SHOW DATABASES。
你的第一步是对数据仓库中的所有表格进行映射,以便了解需要首先跟踪的内容。当这样做时,映射模式可以成为一个强大的工具,让你了解每个表中的内容以及这些内容是如何随时间变化的。
下面是使用Snowflake执行此操作的方法,如示例2-1所示。
示例2-1:通过查询来提取包含相关元数据的表的列表
这段查询语句将获取所有表的列表以及有关其设置的有用元数据。如果你一直在努力使用COMMENT( https://oreil.ly/CZvoU )记录你的数据,会发现它特别有用。
了解表的模式是如何演变的可以真正帮你防止并解决数据损坏问题,而要获得表的模式,你可以使用示例2-2中的查询语句。
示例2-2:检索Snowflake中表的模式
请注意,前面的代码片段对表有所帮助,但我们有意省略了视图和外部表。要提取这些数据的元数据,我们建议使用以下查询指令:
虽然这可能会增加实现的复杂性,但这些查询指令能获取在information_schema.tables查询语句中无法获得的有价值信息。例如,你将拥有视图的文本属性,该属性将提供有关视图底层SQL查询的详细信息。
第2步:监控数据的新鲜度和容量。 跟踪表的容量和新鲜度对了解Snowflake数据的可观测性和数据管道的整体健康状况都非常重要( https://oreil.ly/ICi96 )。值得庆幸的是,Snowflake在对数据仓库中的表进行写入时就能跟踪这些信息。你可以使用该查询指令来获取表中的字节数和行数,以及这些表最近更新的时间,如示例2-3所示。
示例2-3:通过查询来生成与表的新鲜度相关的结果
通过存储这些指标并观察它们随时间变化的情况,你可以映射出表的更新频率、每次更新中预期的数据量,并识别其中缺失或异常的更新。
度量视图的新鲜度和容量并不简单,因为这是底层查询指令中包含的表的函数。就外部表而言,我们建议使用SHOW EXTERNAL TABLES...中的新鲜度信息。
第3步:建立你的查询历史记录。 拥有在Snowflake环境中运行的所有查询的可靠历史记录是解决问题时非常有用的工具,它可以让你准确了解最近一次写入表的方式和时间。更广泛地说,分析查询日志可以帮助映射沿袭(表之间的依赖关系),了解哪些用户使用了哪些资产,甚至可以优化Snowflake实例的性能和成本。
示例2-4是我们用来提取查询日志的查询语句。我们将过滤系统查询和错误查询以减少噪声。这可以提供关于谁在使用给定表格及其用途的重要信息。
示例2-4:提取查询日志
如示例2-5所示,你可能还会发现,查看复制和加载操作的历史来了解数据的加载和移动情况同样也很有价值。这可以为你提供关于表格新鲜度的洞察。
示例2-5:通过查询来收集数据的加载信息
下一步,我们将通过运行查询来监控空值和零值这两个表明可能出现问题的信号,从而进一步分析Snowflake中的数据质量。
第4步:健康检查。 最后,对于某些关键表,你可能希望运行数据质量检查来确保所有字段都被正确填充了,并且具有健康的值。通过跟踪一段时间内的健康指标,并将其与过去的批数据进行比较,你可以在数据中出现一系列数据质量问题时立即发现它们。示例2-6查询了Snowflake数据的历史记录,这将帮助你了解在给定表中可能存在异常的位置。
示例2-6:查询Snowflake数据的历史记录
接下来,你可以跟踪数据中特定数字字段(或分布)的准确性,如示例2-7所示。在这个示例中,我们专门收集了数据在两个字段中的分布信息:account_id和num_of_users。
示例2-7:收集account_id和num_of_users的数据分布信息
在这个示例中,我们在client_hub表中收集了两个字段的健康指标。
对于字符串类型的字段account_id,我们跟踪了完整性(非空值的百分比)、独特性(唯一值的百分比)和通用唯一识别码(UUID)比例(匹配UUID格式记录的百分比)等指标。随着时间的推移,跟踪这些指标将有助于识别账户无ID、重复记录和ID格式错误等常见问题。
对于数字类型的字段num_of_users,我们则跟踪了其他类型的指标,例如零值率(值为0的百分比)、平均值和分位数。随着时间的推移,观察这些指标可以帮助我们识别丢失数据导致计数为零,或导致用户计数出现极大偏离的错误等常见问题。
对于可扩展性,我们仅跟踪了最近的数据(在这个示例中为一天),并假设过去的数据在之前已被查询和存储。这种做法以及必要时进行抽样将让你能够高效且经济地跟踪一些较大的数据集。
为跟踪数据质量指标而提取的信息需要随时能够提供给团队中的其他成员使用,特别是当事情发生变化或你正处于对数据管道进行根因分析的痛苦之中时( https://oreil.ly/Z3Nm5 )。为了更好地处理这些工作流程,在检测到问题时加入自动通知功能并使用集中式且易于导航的用户界面,可以让你快速解决问题,避免陷入持续数天的数据灾难。
在数据仓库环境中可访问的一个元数据的强大来源就是查询日志——它对数据仓库中进行的转换做了记录。查询日志可以让你回答以下问题:
· 谁在访问这些数据?
· 它来自上游的哪里?去往下游的哪里?
· 平均多久执行一次特定的转换?
· 有多少行会受到影响?
这些信息打包在大多数数据仓库供应商的系统表中。Snowflake QUERY_HISTORY( https://oreil.ly/NcspE )表系列、BigQuery的AuditLogs资源和Redshift STL_QUERY( https://oreil.ly/00KBm )表系列是最开始进行此类查询的地方。在Google中搜索“[供应商名称]查询日志”([vendor-name] query logs)可能可以帮助你在数据仓库供应商那里找到类似的查询语句。
查询日志表通常仅存储某些天数的查询历史记录,且其中所包含的信息比数据质量计划所需要的多得多。这意味着,一个处理数据质量指标查询日志的健壮的解决方案需要具有前瞻性,并将所需的指标和聚合存储在一个更为永久的位置。如果我们看看Snowflake和Redshift就会发现,现成的指标将包括:
· 执行查询的用户ID。
· 查询所用到的SQL文本,以及标识它的散列值。
· 查询从开始到结束的总运行时间。
· 如果出现错误,则显示错误代码。
· 查询输入/输出的大小,以行或字节为单位。
这看起来可能不是很多,但如果我们以一种聪明的方式应用元数据去收集现在已有答案的问题呢?例如:
· 上次查询此表是什么时候?
· 更新是常规节奏的一部分,还是打破了常规?
· 作为一天中时间的函数,这个数据仓库的负载是多少?
· 该查询是否比两个月前需要花费更长的时间来完成?
· 谁(或什么软件)有权访问此资源,谁无权访问?
查询日志可以回答这些问题,甚至更多。接下来我们将了解一下它是如何回答的。
正如我们在2.3.2节所讨论的,数据湖与数据仓库的不同之S处主要在于它们允许更为灵活的存储格式。数据湖允许“读时模式”访问协议( https://oreil.ly/SZpui ),该协议允许数据以原始文件格式进行存储并操作。虽然我们之前讨论过这种做法令数据湖具有明显的优势,但同样会增加数据湖的“沼泽化”风险。由于在插入数据时模式不会被系统限制,所以许多在数据仓库架构中存在的数据质量指标在这种情况下很难获得或者无法获得。但令人欣慰的是,现代数据湖依然可以做很多事情来确保数据质量。
你可以免费获得数据湖中的一些元数据。当添加新数据时,数据湖会收集和存储对象的元数据。有些元数据会让你“无意中”受益,例如,Amazon S3恰好需要存储对象插入时间和有效负载大小以用于其对象管理。而你可以利用该元数据来回答“该对象上次更新是在什么时候?”或者“此类文件的平均文件大小是多少,最近是否有所增加?”等问题。
大多数现代数据湖中存在的系统元数据将包括:
· 对象插入时间
· 对象大小(以字节为单位)
· 对象文件格式(如果可以被识别)
· 是否启用了加密
除了系统存储的元数据之外,你还可以在创建对象时指定额外的对象头。在这里,数据质量的解决方案会更加开放。你可以想想在系统定义的元数据中少了哪些你需要用来评估数据宕机时间所需的元数据。
其中一些例子包括:
· 哪个作业管道或用户负责创建此对象?
· 对象使用或依赖什么模式?例如,你可以对上游转换的架构进行散列处理,以判断资源是否针对某个ETL工作流进行了配置,或者转换的一端是否已被弃用。
但是请记住,回答“谁负责创建此对象?”这个问题的另一种方法是实施更严格的控制访问权限,并仅向单个管道授予写入权限。这种方法虽然很费劲,但可以确保更主动地对数据质量进行处理。
数据栈中的另一个关键元素是数据目录,它在理解数据质量方面起着重要的作用。