V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kernelpanic
V2EX  ›  程序员

超过 1TB 的 csv 文件,有没有快速的处理方法

  •  1
     
  •   kernelpanic · 11 天前 · 2039 次点击

    格式:ID ,content ,sort
    需要找到所有相同 ID 的 content ,按 sort 顺序拼接起来存到数据库里,怎样最快?难道要逐个循环吗那也太慢了?大家有没有好的算法?

    22 条回复
    liaojl
        1
    liaojl  
       11 天前 via iPhone
    什么文件啊,这么大😧,社工库?
    woscaizi
        2
    woscaizi  
       11 天前
    导入数据库,然后用 sql 处理
    pwelyn
        3
    pwelyn  
       11 天前
    csv 导入到数据库,然后用数据库的 sql 查询所有具有相同 ID 的记录,然后按 sort 字段排序。不知道行不行
    phrack
        4
    phrack  
       11 天前 via iPhone
    数据库我估计处理起来会遇到问题。

    假设你的内存能装 32g 的数据,那就把这个大文件分成多个文件,每个 32g ,挨个加载进内存排序再写回,最后再 merge sort 。标准操作。
    phrack
        5
    phrack  
       11 天前 via iPhone
    好像读题读错了,不过方法也能用。


    越看越像社工库。
    yianing
        6
    yianing  
       11 天前 via Android
    duckdb 之前看别人用着挺猛的,要不试试?
    kernelpanic
        7
    kernelpanic  
    OP
       11 天前
    不是社工裤,内容类似新闻报道,只不过每个段落一条记录,需要把这些段落按顺序恢复成一篇文章。
    Celebi
        8
    Celebi  
       11 天前 via iPhone
    文本三剑客
    hugi
        9
    hugi  
       11 天前
    @liaojl 江湖上的事少打听
    weak
        10
    weak  
       11 天前 via iPhone
    clickhouse
    ZeroW
        11
    ZeroW  
       11 天前 via iPhone
    无论用什么外部工具,最低的复杂度也需要把所有的数据过一遍建立结构化数据,和你循环一遍差距不大
    marquina
        12
    marquina  
       11 天前 via iPhone
    可以将问题提给 chatgpt ,参考 ai 的思路。
    我的思路是,1 、将 id 相同的记录聚集在一起。2 、遍历每个 id ,将对应的多个数据按 sort 排序。3 、将排序后的数据记录下来。
    marquina
        13
    marquina  
       11 天前 via iPhone
    @marquina #12 第 1 步和第 2 步可以考虑用 shell 的 sort 命令,或者导入数据库并加入索引( id+sort 联合索引)。第 3 步就是写代码,扫描每一行即可。
    SuperXX
        14
    SuperXX  
       11 天前 via iPhone
    Duckdb 或者 Clickhouse 吧,Parquet 文件格式可以显著性的减小你的文件大小, 并且加快读取速度
    zwy100e72
        15
    zwy100e72  
       11 天前
    个人倾向于把复杂度转移给文件系统,一边扫描 csv 一边把内容切开,形成这么个结构 `{id}/{sort}.txt` content 直接写进文件里,这样的话处理逻辑上可以一行一行处理;最后入库的时候再按照你的要求拼接好入库

    时间复杂度上算是做了三轮遍历,空间复杂度上是输入文件的 3 倍左右
    zizon
        16
    zizon  
       11 天前
    docker run 个 spark shell...
    ershierdu
        17
    ershierdu  
       11 天前   ❤️ 1
    不了解最新的分布式架构,但感觉这也太符合 MapReduce 的思路了…

    逻辑上:
    1. 把文件扫一遍,得到 id->list[pair<content,sort>]的映射。
    2. 单独为每个 id 的内容做内部排序。

    实现上:
    1.无论用什么方法,一轮文件 IO 把数据都进来都是需要的。为了后续处理更方便,再多加一轮 IO ,先把大文件按 1<id<10w, 10w+1<id<20w...切成多个小文件,这样每个小文件都是独立的,后续处理时维护的中间状态会少很多。
    2. 每个小文件用一个进程处理,得到 id->list[pair<content,sort>]的中间结果。要么像楼上说的直接进数据库,要么每个 id 的内容放在一个文件里。一个小文件跑完后就可以从中间结果生成最终数据了。

    并行度可以在切小文件的时候控制(每个小文件 10w 还是 100w 个 id )。

    前提:
    你存放最终结果的数据库需要能承受这么大的最终数据,否则啥办法都白搭。
    zzl22100048
        18
    zzl22100048  
       11 天前
    可以先用 duckdb 试试
    ajaxgoldfish
        19
    ajaxgoldfish  
       11 天前 via Android
    切片+逐行建索引。确实如楼上所说,不管干啥都得建立索引,然后读到内存里,在内存里操作快得多。硬盘还得够好,不然读一遍文件的时间就不是个小数。
    kernelpanic
        20
    kernelpanic  
    OP
       11 天前   ❤️ 1
    感谢各位,目前用的最快方法是:从已离职的同事电脑上找到了原始格式,没分段落的那种。。然后直接导入到数据库了。。。
    yifangtongxing28
        21
    yifangtongxing28  
       11 天前
    @kernelpanic 你这个回答,直接打脸楼上所有技术大佬哈哈
    sg8011
        22
    sg8011  
       11 天前
    果然什么技术优化都比不过人的优化吗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1109 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 19:50 · PVG 03:50 · LAX 12:50 · JFK 15:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.