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

2024-06-01 22:14:20 +08:00
 drymonfidelia
15728 次点击
所在节点    程序员
101 条回复
wxf666
2024-06-02 15:33:02 +08:00
@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
2024-06-02 17:01:07 +08:00
学习下
haha1903
2024-06-02 19:34:18 +08:00
hyperloglog
peterxulove
2024-06-02 20:52:53 +08:00
对每一行进行哈希,哈希后的哈希值每个位置的值为一个叶子结点建立二叉树,哈希值的位数就是二叉树的层级,判断的时候遍历二叉树即可。
XuYijie
2024-06-02 20:58:50 +08:00
把数据读到数据库,然后分批处理,或者使用 easyExcel 分批读取,处理后把处理后的数据导出到一个新的 csv
winiex
2024-06-02 21:06:02 +08:00
以行顺序读内容,记录一个每行的 hash 值,发生碰撞抛弃当前行
IwfWcf
2024-06-02 21:19:43 +08:00
如果只是要去重那分块排序就好了,如果要保留原有顺序的话那前面有人提到的 bloom filter 命中的情况下再去数据库查询确认应该是最优方案了
qdwang
2024-06-02 21:21:51 +08:00
203 亿行,每一行做 BLAKE3 ,按照 bit 为 1 的和,来进行分类,共分 256 类。

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

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

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

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

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

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

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

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

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

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

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

© 2021 V2EX