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

Java8 使用 easyExcel 导入 4g 大小的 csv 文件

  •  2
     
  •   jiangboyueplus · 13 天前 via Android · 2216 次点击
    粗略观测,在没完成导入前内存占用已经超 48g 。粗略估算好像是因为我需要将所有的行记录都放到一个 list ,最后聚合处理,这个 list 至少有 9 千万条以上的记录。

    以上,何解?

    1.多次读取 每次只保存需要聚合的数据的一部分.缺点,同一个文件要读好多次 预计会非常耗时

    2.每次读取一行记录都存入数据库,最后从数据库取用。缺点,需要额外的数据库表结构,且 mysql 单表存储也会有查询压力(可以考虑分表,但这个方案挺麻烦的)
    第 1 条附言  ·  12 天前
    不好意思,昨天的描述非常粗略且不完整。对于需求的描述如下:
    是将对方系统导出的 csv ,导入到我方系统。其中是有一些映射关系的。
    有两类 csv ,a 类固定很大,至少 1.5g 以上,b 类可大可小,最大有 4g 大,小的也有几十 m 。楼主最初写这个程序的时候,贪图省事,将 b 类文件的记录相同的某 id 列聚合处理(一组数据含有开始结束等标识)。楼主又贪图省事(毕竟算低频使用的初始导入程序),选择把 csv 全部加载入内存,得到两个 list 方便操作。
    当然了,如果要改一下,使用 easyExcel 或者其他工具逐行读取分若干个小的批次处理也是 OK 的,只是楼主懒,一开始没有这么写,选择了最简单粗暴的方式。
    最后,感谢大家的回复,看到大家的回复受益良多,学到了很多。谢谢
    22 条回复    2024-04-28 22:05:46 +08:00
    imzhoukunqiang
        1
    imzhoukunqiang  
       13 天前 via Android
    改动量最小的方案,用 mapdb ,把 list 映射到磁盘。
    512357301
        2
    512357301  
       13 天前 via Android
    对 Java 不熟,我的方案:
    纯本地,sqlite 或 duckdb 或同类型方案
    100 并发以内,clickhouse 或同类型 olap 方案
    100 以上并发,出门左转找数据团队。
    jiangboyueplus
        3
    jiangboyueplus  
    OP
       13 天前
    @imzhoukunqiang 作为一个数据导入的需求,我就喜欢改动最小的方案。我去了解下
    sagaxu
        4
    sagaxu  
       12 天前
    大 csv 不要用 easyExcel 读,用 commons csv ,CSVParser 可以迭代器访问,不用全部载入内存

    边读边聚合,一次汇总完所有指标,同一个文件只读一次

    分表是分布到多个机器利用集群性能,或者把冷热数据分离降低规模,此处不适用
    perbugwei
        5
    perbugwei  
       12 天前
    9 千万条数据,那必然爆。
    存到 mysql ,超过两千万也有问题。
    不改程序,操作一下 csv ,把 csv 分割成多个 sheet 。
    luozic
        6
    luozic  
       12 天前   ❤️ 1
    这明显是 duckdb 的场景,关键是 duckdb 用得多案例多,mapdb 维护都没看到什么了
    cslive
        7
    cslive  
       12 天前
    shell 直接导入 csv 文件
    Arivan996
        8
    Arivan996  
       12 天前
    最核心的问题不是所有的数据都在内存中没做处理吗?
    Karte
        9
    Karte  
       12 天前
    核心问题是你要拿这些数据做什么?
    Karte
        10
    Karte  
       12 天前
    有谁会把 9 千万条数据一起做聚合的? 分批次聚合都能解决问题.
    BBCCBB
        11
    BBCCBB  
       12 天前
    easyexcel 也是可以增量解析的, 你的问题在于要把所有数据都加到内存里.
    winglight2016
        12
    winglight2016  
       12 天前
    lz 不说完整的需求,这个问题无解

    如果是纯聚合计算,用 spark 吧
    beetlerx
        13
    beetlerx  
       12 天前   ❤️ 3
    这不是 1BRC 很像么 看看这个
    https://www.cnblogs.com/thisiswhy/p/18051585
    dooonabe
        14
    dooonabe  
       12 天前
    需求太模糊了
    wxf666
        15
    wxf666  
       12 天前
    @luozic #6 感觉 DuckDB 读文件时,性能有点问题?


    感觉 DuckDB 读空缓冲区后,Writer 才能继续写。写满后,DuckDB 才去读一样?

    同样的内容,会因喂给 DuckDB 的姿势不同,表现出不同的速度差异。。

    就像 Python 的假多线程一样,只能有一个线程活跃。。

    yazinnnn0
        16
    yazinnnn0  
       12 天前
    边读边算呗, 为啥要全读完
    luozic
        17
    luozic  
       12 天前
    @wxf666 你是是把 duckdb 当 sqlite 用了
    xubeiyou
        18
    xubeiyou  
       12 天前
    @beetlerx 看完了 这个确实不错 这么一想 都是写 Java 的差别是真 TMD 巨大
    Vegetable
        19
    Vegetable  
       12 天前
    有点抽象了,一个导入的需求而以,非得读到内存全量操作,就没有什么流式处理的可能吗?
    credo123
        20
    credo123  
       4 天前
    @beetlerx 这个我也看了,很牛.
    fengpan567
        21
    fengpan567  
       1 天前
    搞 2 张临时表,用先将原始数据初始化进去,然后存储过程批量计算 insert
    jiangboyueplus
        22
    jiangboyueplus  
    OP
       1 天前 via Android
    @fengpan567 这也可以,就是现在很多人不可能没用过存储过程
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1276 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:36 · PVG 07:36 · LAX 16:36 · JFK 19:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.