使用Apache PySpark解析数据时确保类型安全
数据工程师的主要任务之一就是要从多个来源摄取数据。这些来源可以是API端点、流媒体服务、上传文件到云端的cron作业等等。从这些源头摄取的数据被倾倒到数据库中,随后被用于解析和ETL中的下游业务逻辑。
但这里存在的问题是。当涉及到它们产生的字段的数据类型时,我们能依靠源系统,特别是第三方吗?
与其依赖这些源系统,不如在消费层面卸载类型检查和类型转换的过程,即让数据消费者根据他们的需要定义目标数据类型。
本文介绍了一种确保解析器类型安全的方法及其优点和缺点。
该方法
以JavaScript对象符号(JSON)格式的数据为例,JSON中的字段可以是多种类型。有时,我们甚至可能不知道哪些字段有哪些数据类型,这就使得跟踪并确保正确维护各个字段的类型变得非常困难。
因此,在JSON模式所包含的所有字段中执行统一性是至关重要的。最安全的方法是在模式树的所有叶子节点中强制执行StringType。A 叶子结点 是一个字段,可以是字符串或大数或时间戳等类型,但不能是结构类型或数组类型。
让我们看一下如何做到这一点。
考虑到你已经将JSON数据加载到一个数据框架中,JSON列以json的名字出现。
首先,模式是由json列推断出来的。然后, enforce_stringtype函数对从Spark推断的模式中获取的模式元数据执行深度优先搜索(DFS)。它检查模式元数据中的一个特定字段是否是叶子。如果是叶子字段,它将所有叶子字段(非结构或数组类型的字段)转换为字符串并返回,否则,它将遍历结构或数组字段内部并将所有叶子字段转换为字符串类型。
然后,模式元数据被转换回StructType,以用于在json列上执行改变的模式。
然后,所需的转换可以应用于可以从type_safe_json列获得的字段,以便转换为数据消费者指定的目标数据类型。
优点
这种方法有几个优点。
- 转换到StringType不会导致任何数据丢失,也不会在消化后和预消费过程中丢弃行。
- 源对JSON中的字段所做的任何数据类型的改变,例如,从整数到双数,都由这种方法处理。
- 强制执行StringType后所做的转换可以确保一个特定的字段有一个设定的数据类型。
结论
尽管这种方法提供了一些优点,但它也有一些缺点。
- 在强制执行StringType后应用于字段的转换是一个额外的计算。此外,如果源系统是可靠的,这些字段可能已经具有目标数据类型。由于它们被转换为字符串并返回到目标数据类型,这意味着一个多余的计算。
- 为要应用转换的字段设置目标数据类型是一项手工工作。如果有大量的字段需要应用转换,这可能会变得很繁琐。
- 下移会导致数据丢失(比如double到int),这必须由消费者来解决。
总而言之,相信源系统会保留每个字段的相同数据类型是值得怀疑的。这种方法可以用来确保安全,避免源系统产生的任何类型的数据类型冲突,其缺点也很明显,上面提到过。将指定目标数据类型的过程转移给消费者,使解析器独立于任何数据类型检查。这也符合在数据被消费时决定模式的要求。