2015年7月14日星期二

大数据差异比较

问题:
有两份数据A和B,要求求解A和B的内容差异?
前提条件:
1. A和B使用文件保存,且数据量在G级别;
2. A和B的文件内容是结构化的;
3. A和B的文件内容是乱序的,即A的第一行可能在B中,但是在第n行,也可能不存在,B也一样。

解决方案:

1.linux diff命令

缺点:diff对文件进行按序比较,比如:
a.txt:
1 a
2 b
4 d
3 c
b.txt
2 b
4 d
3 c
1 a
5 e
执行命令:diff a.txt b.txt
1d0
< 1 a
4a4,5
> 1 a
> 5 e
分析结果可知,A和B同时包含的数据依然出现在结果中,需要对结果进行额外处理。当数据量较大时,diff运行超级慢。

2 分桶+grep
描述:A和B的数据是结构化的,因此可以取一列进行hash,将A和B进行分桶,比如分桶至128个文件中,然后分别比对A(1-128)和B(1-128)。
比对时,使用grep命令逐行扫两个文件即可。分桶可以使得grep的文件规模降低。
缺点:这是一个很笨的方法,速度及其慢。我采用了这个方法。呵呵!

3 sort+comm

sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式:
  sort [-bcfMnrtk][源文件][-o 输出文件]
补充说明:sort可针对文本文件的内容,以行为单位来排序。

参  数:
-b 忽略每行前面开始出的空格字符。
-c 检查文件是否已经按照顺序排序。
-C会检查文件是否已排好序,如果乱序,不输出内容,仅返回1。
-f 排序时,忽略大小写字母。
-M 将前面3个字母依照月份的缩写进行排序。
-n 依照数值的大小排序,防止10比2小的情况。
-o<输出文件> 将排序后的结果存入指定的文件。
-r 以相反的顺序来排序。
-t<分隔字符> 指定排序时所用的栏位分隔字符。
-k 选择以哪个区间进行排序。
-u 在输出行中去除重复行

例如,对a.txt进行排序:sort -n -k 1 -t ' ' a.txt

comm命令——对已经有序的文件进行比较
comm对文件进行处理时,要求文件已经有序,如果没有顺序,请使用sort进行排序后进行处理。语法:
comm [-123][--help][--version][第1个文件][第2个文件]

补充说明:
这项指令会一列列地比较两个已排序文件的差异,并将其结果显示出来,如果没有指定任何参数,则会把结果分成3行显示:
第1行仅是在第1个 文件中出现过的列;
第2行是仅在第2个文件中出现过的列;
第3行则是在第1与第2个文件里都出现过的列。

若给予的文件名称为"-",则comm指令会从标 准输入设备读取数据。
参数:
-1 不显示只在第1个文件里出现过的列。
-2 不显示只在第2个文件里出现过的列。
-3 不显示同时在第1和第2个文件里出现过的列。
例如:
comm a.txt b.txt 
               1 a
                2 b
                3 c
                4 d
        5 e
缺点:对于大文件,依然很慢。

4 egrep
egrep -f a.txt -v b.txt

5 使用hadoop和hive
最终采取的方案。
因为A和B都是结构化数据,因此可以使用hadoop和hive。创建两张表,将A和B分别载入,然后求内容差集。

使用hive的 关键字left semi join,解决的问题是:IN/EXISTS,即求并集。
例如:
select test_1.id, test_1.num from test_1 left semi join test_2 on (test_1.id = test_2.id);

使用hive的关键字left outer join, 解决A差B的问题:
例如:
select test_1.id, test_1.num from test_1 left outer join test_2 on (test_2.id = test_2.id) where test_2.num is null;

没有评论:

发表评论