要对单个 6.20TB 的超大 csv 文件保持顺序的情况下进行去除重复行,有什么好思路?显然不可能加载进内存

32 天前
 drymonfidelia
8952 次点击
所在节点    程序员
101 条回复
wxf666
31 天前
@phrack #15

突然想起来,zram 可能行不通。。

sha1 的结果,是不是相当于随机数据?随机数据,压缩不了啥吧。。

即,256 GB 内存,当不了 512 GB 用?全都用来存压缩比 100% 后的数据了?


@cabbage #57

需要保留 27 行原始 string ,在小根堆里。

第二步目的:检查出各块中,偏移量非最小的重复行,记录进删除名单中。

第二步时,已经有 26.5 个 240GB 的、排序好的块。

参考多路归并,可以流式构造出有序的 (string, offset, chunk_index)。

当 string 与上一个不同时,说明碰到偏移量最小的新行了(即,全文首次出现)。

当 string 与上一个相同时,说明重复行了,此时往 "to_del_${chunk_index}.txt" 里记录 offset 。

(可以攒多点再写,反正只用了 27 个字符串 + 27 * 1GB 缓冲区,还剩 200+GB 内存呢。。)

以前写过类似的,10+ MB 内存去重 13 GB 文件,里面也有用到多路归并:/t/1031275#reply15
conan257
31 天前
学习下
haha1903
31 天前
hyperloglog
peterxulove
31 天前
对每一行进行哈希,哈希后的哈希值每个位置的值为一个叶子结点建立二叉树,哈希值的位数就是二叉树的层级,判断的时候遍历二叉树即可。
XuYijie
31 天前
把数据读到数据库,然后分批处理,或者使用 easyExcel 分批读取,处理后把处理后的数据导出到一个新的 csv
winiex
31 天前
以行顺序读内容,记录一个每行的 hash 值,发生碰撞抛弃当前行
IwfWcf
31 天前
如果只是要去重那分块排序就好了,如果要保留原有顺序的话那前面有人提到的 bloom filter 命中的情况下再去数据库查询确认应该是最优方案了
qdwang
31 天前
203 亿行,每一行做 BLAKE3 ,按照 bit 为 1 的和,来进行分类,共分 256 类。

平均每类大小 20300000000 * 256 / 8 / 1024 / 1024 / 1024 / 256 = 2.36G

存成 256 个分类文件,根据你可用内存大小,载入对应数量的分类在内存里作为 cache 。未命中,就随机内存里去除一个,替换成新的。也很容易做成分布式,每台机器管理一定数量的分类。

由于 BLAKE3 目标是 128bits 安全,所以你可以缩小到 128bit 使用,256g 内存电脑可以装得下 210 个分类在 cache 里。
qdwang
31 天前
说错了,BLAKE3 使用 128bit 后,每个分类仍然是 2.36g ,但是分类数量减小到 128 个。
vivisidea
31 天前
1. 计算每一行的 hash , 保存到文件里 hashes.txt
2. 对 hashes.txt 进行外部排序,外部排序对内存要求低,压力给到磁盘
3. 遍历 hashes.txt 找出重复,因为已经有序,所以简单对比当前行和上一行即可知道是否重复
Hawthorne
31 天前
不能用内存映射吗?
psyer
31 天前
@XuYijie pandas 的 easyExcle?会不会非常慢…
psyer
31 天前
pyspark 效果如何?😁
qinrui
31 天前
emeditor 直接打开处理
cocalrush
31 天前
直接用阿里云的 odps 生成个离线表跑下是不是就行了...
Keuin
30 天前
awk 每行尾追加逗号和行号,整个文件每个行都追加一下,占 6.2T
unix sort 工具外排序,直接按字母表排序,占 6.2T 。重复行会变成相邻的,编号不一样。输出另占 6.2T
用 awk 配合 uniq ,去重,全内存 O(1)空间算法,输出占 6.2T ,即为最终结果

中间文件可以在不用的时候删掉,最大同时出现 2 份,也就是需要额外 2*6.2T 磁盘空间,由于都是流式算法,内存用量为很小的常数
Keuin
30 天前
@Keuin 最后还差一步,按行号升序排序,重新排序回原来的顺序,最大额外磁盘空间不变
qbmiller
30 天前
再来一个文件 csvA. 然后这 2 文件 ,双指针遍历. A 放不重复的,
基于顺序的话,是可以的
blankmiss
30 天前
或者你给个脱敏德样本数据出来看
cndenis
30 天前
@wxf666 如果需要严格不能丢数据的话, 不能单用布隆过滤器.

假设重复率比较低的的话,, 可以做两轮读取

第一轮边读边构造布隆过滤器, 把发现的冲突的行记录到数据库

第二轮先把数据库中值导入新的布隆过滤器, 然后用它来过滤原表, 对有冲突的行查用数据库确证没重复再输出

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

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

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

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

© 2021 V2EX