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

想起几年前刚毕业有一道面试题。

  •  
  •   frank1256 · 195 天前 · 3551 次点击
    这是一个创建于 195 天前的主题,其中的信息可能已经有所发展或是发生改变。

    语言限制 Java 吧,内存 4g 。

    效率最高 从 Msql 里读取 50W 条数据,写入 execl 的方法。

    现在想想这个题目,我给的答案是游标读取 mysql ,randomAccess 或者 nio 写入 execl ?各位大佬指点指点,感觉好像怪怪的。

    15 条回复    2022-09-19 08:53:58 +08:00
    misaka19000
        1
    misaka19000  
       195 天前
    一条数据多大
    wangyiyi10
        2
    wangyiyi10  
       195 天前
    感觉应该是顺序写 csv 文件吧? EXCEL 可以打开是不是就满足写入 excel 了。
    makdon
        3
    makdon  
       195 天前
    读 mysql 可以并行分页拉,这样瓶颈在网络带宽 /MySQL 性能
    写文件如果是 xlsx 的话可能比较慢,如果是 csv ,用 mmap 写应该会快一点?
    题目信息有点少,应该是展开聊的开放题吧
    VensonEEE
        4
    VensonEEE  
       195 天前
    各位大佬,50W 很多么?能写 excel 的,估计也没有大字段吧,4G 内存还不够?
    az467
        5
    az467  
       195 天前
    多线程提效率,减少 CPU 浪费,流式处理防止 OOM 。

    不过五十万这数据量也太小了。
    mylifcc
        6
    mylifcc  
       195 天前
    其实就是考一个数据几 k 一次读满 4g 多少条 这种思维 感觉没啥卵用
    berg223
        7
    berg223  
       194 天前   ❤️ 2
    假设一行数据有 50 个字段,每个字段 8 字节,一行占用 50*8=400B ,大约 2.5 分之一 KB ,50w 除以 2.5 大概 200MB ,数据量不算大,4g 内存大概是这个规模的 20 倍,不算大的,也就是说每个字段 8 字节,1000 个字段才会在内存上有瓶颈。瓶颈是在 io 上,假设数据是写到同一块机械硬盘上,仅考虑性能的话,在写的时候实际上都不需要并发和 nio 啥的,直接拼接成一个 csv 格式的字符串往硬盘上怼,最大化利用磁盘顺序写的特性,这样速度理论上应该最快。但是实际工作中考虑扩展性不应该这么干。事实上这块的 io 应该是 ms 级别的。
    假设要读取的 mysql 数据是同一块硬盘,多线程也不一定比单线程快,因为瓶颈在于 io 上,读取的 io 分两类,一个是程序和 mysql 之间的网络连接,另一个是 mysql 读取磁盘的 io 。对于第二类肯定单线程比多线程快,对于第一类来说多连接应该比单连接要快,假设机房带宽是 100Mbps=12.5MB ,那么单连接传输 200MB 数据大概需要 200/12.5=16 秒,假设磁盘速度是 100MB/s 的话,单次读取所有数据就只需要 200/100=2 秒,加在一起就是 18 秒,开 x 个连接读取等量数据大概需要 16+2/x 秒,优化空间是秒级别的,最大优化空间不超过 2s ,当然不是 x 越大越好。
    综上,这题最多优化 2s ,未优化前速度大概是 20s 左右,确实没多大优化空间。
    berg223
        8
    berg223  
       194 天前
    @berg223 更正下,事实上这块的 io 应该是 ms 级别的更正为 “事实上这块的 io 的优化空间应该是 ms 级别的”。
    berg223
        9
    berg223  
       194 天前
    @berg223 回头看了下直接拼接成字符串往磁盘上怼应该是有问题的,需要把 jvm 的常量池设置大一些。。
    berg223
        10
    berg223  
       194 天前
    @berg223 还是不对,字符串常量是在堆中的,只有字面量才会在常量池中,所以应该注意的不应该是常量池的大小。
    noparking188
        11
    noparking188  
       194 天前
    @berg223 #7 老哥解答的很棒
    我 Java 不熟悉,不过稍微熟悉一点 Spark ,Spark 读 JDBC 的时候有一些参数设置提供范围分区并发读取,不过需要一个数字类型主键。对于文件 IO ,这个也许可以参考 Kafka 写优化的特点
    reeco
        12
    reeco  
       194 天前 via iPhone
    这有啥难的
    nuk
        13
    nuk  
       193 天前
    excel 写的时候有缓存,xml 构造不会慢,所以瓶颈是 mysql 读,而多线程读 mysql 肯定是更快的,所以这其实就是 MPSC 的问题。
    YepTen
        14
    YepTen  
       193 天前
    我怎么感觉面试官是在问怎么把数据库数据写成 Excel 文件。其他语言不知道,但 java 写 Excel 之前是 POI ,这玩意可耗内存啊,之后是用阿里的 EasyExcel 。50W 的数据对数据库来说不是毛毛雨,直接读就是了。问题应该是在如何写,而不是读。
    YepTen
        15
    YepTen  
       193 天前
    如果现在问这个问题,限定 Java 的话,就是直接读+EasyExcel 。一个方法里就写完了,我写过 100 万的数据到 Excel 表里,一点问题没有。
    关于   ·   帮助文档   ·   博客   ·   nftychat   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   4530 人在线   最高记录 5556   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 103ms · UTC 09:03 · PVG 17:03 · LAX 02:03 · JFK 05:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.