1
liprais 2016-09-07 15:35:19 +08:00
装个数据库,弄到数据库里,让数据库帮你做这些事
数据库发展了二三十年了,对于这种操作优化的很好,比自己写算法实现轻松多了 |
2
xuqd 2016-09-07 15:39:44 +08:00
外排序
|
4
xderam 2016-09-07 18:00:23 +08:00
呃,来个运维思维。用 uniq 和 awk 是否也可以?当然没考虑过效率。。
|
5
helloworld2010 2016-09-07 18:02:30 +08:00
分区段去重不就可以了,一块去重完,再合并到相邻块去重……不知道这思路可行么
|
6
Layne 2016-09-07 18:14:27 +08:00
@helloworld2010 只要最终去重后的数据量还是无法一次载入内存,应该还是达不到效果吧
|
7
9hills 2016-09-07 18:17:09 +08:00 1
|
9
Magic347 2016-09-07 18:18:54 +08:00
自己实现的话,显然采用 2 楼的方法,
1. 把原文件分块,分成 n 个小文件依次 load 进内存进行内存排序,并输出 n 个有序小文件 2. 对 n 个有序小文件执行 merge 操作,生成 1 个合并后的有序大文件 3. 逐行扫描该有序大文件,去除重复行数据即可 注意几点: 1. 分块以后的小文件大小要保证可以全量 load 进机器内存 2. merge 时,内存仅需维护一个 n 元素的二叉堆即可,开销大头在于磁盘 IO (因为要反复进行文件读写操作) 这应该是一道很经典的有关海量数据去重的面试题, 扩展到分布式计算领域,可以借鉴 Map-Reduce 的思想(如果楼主有兴趣进一步了解)。 |
11
hanzhichao2000 2016-09-07 18:37:20 +08:00 via Android
blaze 或 dask ,语法类似 pandas ,比数据库和 Hadoop 都轻
|
12
matrix67 2016-09-07 18:39:24 +08:00 via Android
又不是整天去,效率没关系。逃,
|
13
lll9p 2016-09-07 18:45:25 +08:00
推荐用数据库,比 Pandas 效率高
|
14
dl2k 2016-09-07 18:46:52 +08:00 via iPhone
其实本质上都会考虑用摘要方法来减少用于去重比较的数据量 不过摘要总归会遇到碰撞问题
而且如果数据规模极端点 摘要数据依然可能过大的可能 其实最通用的方法是先轮询一遍数据 根据一种可以避免把相同数据分在不同组的分组算法 比如 md5 后取模 把数据分成 n 个文件 每个文件小于内存大小 然后轮询这些文件进行单独去重 最后合并数据 这个方法大概需要和数据等量的磁盘空间 |
15
ooonme 2016-09-07 18:54:19 +08:00 via iPhone
会 python 的话 pyspark 一行代码搞定
|
16
zhangchioulin 2016-09-07 19:15:13 +08:00
@Layne 哈哈哈 ... 你的头像
|
17
renzhn 2016-09-07 19:32:49 +08:00 via iPhone
你可以:
1. 进对数据进行排序,此操作不需要大量内存,可以用 sort 命令 2. 过滤掉重复出现的行,可以只直接用 uniq -d |
18
tolerance 2016-09-07 19:37:53 +08:00
Bloom Filter , bitmap
|
19
renzhn 2016-09-07 19:41:08 +08:00
第二步应该是 uniq -u
这两步操作都不需要把所有的数据读入内存 |
20
renzhn 2016-09-07 19:45:49 +08:00
不对 应该是无参数的 uniq
|
21
incompatible 2016-09-07 19:53:00 +08:00
@vinceguo 你这就好比面试时别人让你写代码实现快排,你却直接找了个现成的库函数调用了一下。工具的奴隶。
|
22
mringg 2016-09-07 19:54:14 +08:00 via Android
估算下去重的数据量
|
24
necomancer 2016-09-07 19:56:11 +08:00
试试布隆表。。。 pandas 直接是够呛了吧
|
25
zmj1316 2016-09-07 20:26:46 +08:00 via Android
同意上面说的,先用摘要算法分块再做
|
26
vinceguo 2016-09-07 20:35:04 +08:00 via Android
@incompatible 煞笔,你从硅提纯开始做起吧
|
28
gladuo 2016-09-07 21:30:06 +08:00
解决问题的话用数据库或者 spark ;
面试的话 hash 或者 分块进行 merge 再合并; 如果预计去重之后内存还是放不下,该升级内存了 :) |
29
Layne 2016-09-08 00:47:11 +08:00
@zhangchioulin 哈哈哈哈,你的头像自己改了字母?
|
30
9hills 2016-09-08 07:58:18 +08:00
地图炮下,假如这是一个面试题目,凡是说排序的,统统不得分
做个简单的测试,首先生成 3000w 行随机数,去重后是 1000w seq 1 10000000 > 1000w cat 1000w 1000w 1000w > 3000w shuf 3000w > 3000w.shuf 然后用 awk hash 的方法去做去重。结果如下 资源占用: 1G 内存, E5-2650 v3 @ 2.30GHz 一个核 时间消耗: 35s $ time awk '{if($1 in a){}else{a[$1];print $1}}' 3000w.shuf > 1000w.out awk '{if($1 in a){}else{a[$1];print $1}}' 3000w.shuf > 1000w.out 34.12s user 0.95s system 99% cpu 35.107 total 说排序的,谁能用单机排序去重做到 35s ? |
31
zhangchioulin 2016-09-08 09:52:08 +08:00
@Layne 改了~
|
32
Magic347 2016-09-08 10:27:02 +08:00
@9hills
这个应用场景下,题主的痛点显然是资源的受限(现有机器的内存资源不足以 1 次完成全量数据的加载和去重), 对于执行时限上显然不必要求如此苛刻。 而事实上,基于外排序的思想,这一类问题往往易于扩展到海量数据的分布式并行处理上。 而所谓的海量数据就不仅仅是 1 亿条数据那么多了,可能是 TB 量级甚至 PB 量级的, 到那时你还指望你那玩具命令可以跑出结果吗?自己体会一下吧。 |
33
9hills 2016-09-08 11:44:30 +08:00
@Magic347 Talk is cheap , show me your code 。
别 TB , PB ,你就写个 3000w 行排序去重给我看看,呵呵 事实上,你以为 hash 不能分布式扩展?去重一定要排序?呵呵 |
34
9hills 2016-09-08 11:46:24 +08:00
@Magic347 再说资源, lz 不过 1 亿条未去重数据,按照 hash 来说 8G 足够了。这个就是一个正确的解决方法
你说有其他解决办法, OK , code 拿出来 看看,在 8G 内存条件下,看谁更快 |
35
9hills 2016-09-08 12:03:31 +08:00
恰好前不久用 13 台机器+Spark 做了一个排序
100G 的原始数据,需要接近 40min 但是如果用 分布式去重算法的话, 1min 以内 有的时候不能盲目 MR ,盲目 Spark ,不先自己思考下 |
36
Magic347 2016-09-08 14:22:58 +08:00
@9hills 见 9 楼,如果你连外排序的思想都没有建立起来过的话,我只能说基本功未必扎实。
你想一下,当年 google 是怎么利用几百兆内存的低配机器搭起来大规模分布式集群的。 不要总纠结在要怎么利用 8G 内存把程序跑得更快这件事情上了。 |
38
9hills 2016-09-08 14:53:46 +08:00
|
39
9hills 2016-09-08 15:02:40 +08:00
|
40
zmrenwu OP @9hills 嗯,此法值得一试,不过由于我的数据重复率是十分低的,因此可能基于 hash 什么的算法内存依然还是装不下。
|