分享大量数据去重的方法,顺便问下 python 内存占用问题

2016-04-18 22:01:48 +08:00
 cdwyd

单个文本文件,大小 11G ,数据总量 6000 万左右,去重后约 4000 万,去重的依据是 md5 值列。

首先尝试的方法是:建立 md5 的唯一索引, load data infile 语句导入,跑了一个晚上没跑完。 后来取 md5 的前三位进行判断,把不重复的数据写到新的文本文件,去掉唯一索引,再次用 load data infile 语句导入,共计( 10 + 8 = 18 分钟)。

代码大致如下,问题是,这段代码运行后会把 6G 内存全部用完(系统 1G , python 占用 5G ),想问下怎么会占用这么多内存?

import time

start_time = time.time()
lines = []


md5s = {}
for x in 'abcdef1234567890':
    for y in 'abcdef1234567890':
        for z in 'abcdef1234567890':
            md5s[x + y + z] = set()

with open('files.txt', 'r', encoding = 'utf-8') as f:
    for i, line in enumerate(f):
        try:
            if i % 10000 == 0:
                print(i)
            md5 = line.split('|')[3]
            key = md5[:3]
            if md5 not in md5s[key]:
                md5s[key].add(md5)
                lines.append(line)
                if len(lines) > 10000:
                    with open('new.txt', 'a', encoding = 'utf-8') as f:
                        f.write(''.join(lines))
                    lines = []
        except Exception as e:
            print(e)
            print(line)

with open('new.txt', 'a', encoding = 'utf-8') as f:
    f.write(''.join(lines))
lines = []

print((time.time() - start_time) / 60)
14661 次点击
所在节点    Python
34 条回复
ytmsdy
2016-04-19 10:10:38 +08:00
先把这 11G 的文本导入到数据库,然后再在数据库里面做去重复的操作。你这么一边插入,一边查询效率很低的。
SlipStupig
2016-04-19 10:48:06 +08:00
@cdwyd mmap 读取文件,然后用 set 去重, mmap 申请的不是 buff 而是内存分页,只要你是 64 位系统就能突破限制
hitmanx
2016-04-19 10:50:17 +08:00
@decaywood 没太明白,请问具体怎么操作,比如归并时是否排序呢?如果排序就要 O(nlgn)( lz 的方法只要 O(n));如果不排序,最后归并的时候依然是 2 个或多个大文件,依然很占内存。
hitmanx
2016-04-19 11:18:16 +08:00
@decaywood 请忽略上一条信息= =,明白你的意思了~~
hwsdien
2016-04-19 11:47:59 +08:00
我们用 Hadoop 每天对 200G 的文件去重
0xccff
2016-04-19 13:21:28 +08:00
我去过重,之前有个 1200 万条 url ,感觉个人电脑如果不用算法,直接比较的话,太费时了,后来就用了布隆过滤器,不过有误伤的,但通过参数可以控制,对内存的占用还好。
necomancer
2016-04-19 13:30:29 +08:00
要不要去看看神器 sort 和 uniq 的代码?楼主看明白了求带^_^
mathgl
2016-04-19 13:45:22 +08:00
sqlite
hicdn
2016-04-19 14:11:40 +08:00
awk -F'|' '!a[$4]++' files.txt > new.txt
6david9
2016-04-19 17:17:38 +08:00
布隆过滤器?
neoblackcap
2016-04-19 23:16:11 +08:00
去重首先想到 Bloom Filter,
当然 6000 万的数据,我觉得用个数据库也可以简单解决,最多就是时间长一些。
ksupertu
2016-04-20 02:29:50 +08:00
kettle 、 pandas 都有去重模块,还支持几乎所有数据格式及数据库连接,做一个愉快的调包侠就行了啊,自己写的效率肯定没人做量化的人写出来的效率高
KIDJourney
2016-04-20 20:38:33 +08:00
为何要用 md5 ?
cdwyd
2016-04-20 21:43:29 +08:00
@KIDJourney
md5 是已存在的列

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/272090

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX