是否有任何方法来比较两个avro文件以查看数据中存在哪些差异?

qfe3c7zg  于 2021-06-02  发布在  Hadoop
关注(0)|答案(1)|浏览(310)

理想情况下,我希望像sas proc compare这样的软件包可以提供:
每个数据集的行数
一个数据集中存在但另一个数据集中不存在的行数
存在于一个数据集中但不存在于另一个数据集中的变量
两个文件中格式不同的变量(我意识到这对于avro文件来说是很少见的,但是在不破译错误的情况下快速知道会很有帮助)
每列不匹配行的总数,以及列的所有不匹配或任何20个不匹配(以最小者为准)的表示
我已经找到了一种方法来确保数据集是等价的,但是效率很低。假设我们有两个100行5列的avro文件(一个键和四个float特性)。如果我们连接这些表并创建新的变量,这些变量是来自数据集的匹配特征之间的差异,那么任何非零差异都是数据中的一些不匹配。从那里可以很容易地确定上面的整个需求列表,但似乎有更有效的方法。

qaxu7uf2

qaxu7uf21#

avro文件分别存储模式和数据。这意味着除了包含数据的avro文件之外,还应该有一个模式文件,通常类似于*.avsc。这样,您的任务可以分为3部分:
比较架构。通过这种方式,您可以获得在这些文件中具有不同数据类型、具有不同字段集等的字段。这项任务非常简单,可以在hadoop之外完成,例如在python中:

import json
schema1 = json.load(open('schema1.avsc'))
schema2 = json.load(open('schema2.avsc'))
def print_cross (s1set, s2set, message):
    for s in s1set:
        if not s in s2set:
            print message % s
s1names = set( [ field['name'] for field in schema1['fields'] ] )
s2names = set( [ field['name'] for field in schema2['fields'] ] )
print_cross(s1names, s2names, 'Field "%s" exists in table1 and does not exist in table2')
print_cross(s2names, s1names, 'Field "%s" exists in table2 and does not exist in table1')
def print_cross2 (s1dict, s2dict, message):
    for s in s1dict:
        if s in s2dict:
            if s1dict[s] != s2dict[s]:
                print message % (s, s1dict[s], s2dict[s])
s1types = dict( zip( [ field['name'] for field in schema1['fields'] ],  [ str(field['type']) for field in schema1['fields'] ] ) )
s2types = dict( zip( [ field['name'] for field in schema2['fields'] ],  [ str(field['type']) for field in schema2['fields'] ] ) )
print_cross2 (s1types, s2types, 'Field "%s" has type "%s" in table1 and type "%s" in table2')

下面是一个模式示例:

{"namespace": "example.avro",
 "type": "record",
 "name": "User",
 "fields": [
     {"name": "name", "type": "string"},
     {"name": "favorite_number",  "type": ["int", "null"]},
     {"name": "favorite_color", "type": ["string", "null"]}
 ]
}

{"namespace": "example.avro",
 "type": "record",
 "name": "User",
 "fields": [
     {"name": "name", "type": "string"},
     {"name": "favorite_number",  "type": ["int"]},
     {"name": "favorite_color", "type": ["string", "null"]},
     {"name": "test", "type": "int"}
 ]
}

输出如下:

[localhost:temp]$ python compare.py 
Field "test" exists in table2 and does not exist in table1
Field "favorite_number" has type "[u'int', u'null']" in table1 and type "[u'int']" intable2

如果模式相等(如果模式不相等,则可能不需要比较数据),那么可以按以下方式进行比较。匹配任何情况的简单方法:为每一行计算md5散列,根据这个md5散列的值连接两个表。if将为您提供两个表中相同的行数、表1特定的行数和表2特定的行数。在hive中很容易实现,以下是md5自定义项的代码:https://gist.github.com/dataminelab/1050002
要比较字段与字段,必须知道表的主键,并在主键上连接两个表,比较字段
以前我为表格开发了比较函数,它们通常如下所示:
检查这两个表是否存在且可用
比较他们的模式。如果在schema-break中有一些错误匹配
如果指定了主键:
使用完全外部联接在主键上联接两个表
为每行计算md5哈希
带诊断输出主键(pk只存在于表1中,pk只存在于表2中,pk存在于两个表中,但数据不匹配)
获取每个有问题类的100行,与两个表连接并输出到“mistmatch example”表中
如果未指定主键:
为每行计算md5哈希
表1与表2在md5hash值上的完全外部联接
计算匹配行数,仅表1中存在行数,仅表2中存在行数
获取每个mistmatch类型的100行样本并输出到“mistmatch example”表
通常开发和调试这样一个函数需要4-5个工作日

相关问题