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

2022-09-17 11:06:30 +08:00
 frank1256

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

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

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

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

不过五十万这数据量也太小了。
mylifcc
2022-09-17 16:05:38 +08:00
其实就是考一个数据几 k 一次读满 4g 多少条 这种思维 感觉没啥卵用
berg223
2022-09-17 18:17:43 +08:00
假设一行数据有 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
2022-09-17 18:18:45 +08:00
@berg223 更正下,事实上这块的 io 应该是 ms 级别的更正为 “事实上这块的 io 的优化空间应该是 ms 级别的”。
berg223
2022-09-17 18:51:21 +08:00
@berg223 回头看了下直接拼接成字符串往磁盘上怼应该是有问题的,需要把 jvm 的常量池设置大一些。。
berg223
2022-09-17 18:56:39 +08:00
@berg223 还是不对,字符串常量是在堆中的,只有字面量才会在常量池中,所以应该注意的不应该是常量池的大小。
noparking188
2022-09-17 22:09:17 +08:00
@berg223 #7 老哥解答的很棒
我 Java 不熟悉,不过稍微熟悉一点 Spark ,Spark 读 JDBC 的时候有一些参数设置提供范围分区并发读取,不过需要一个数字类型主键。对于文件 IO ,这个也许可以参考 Kafka 写优化的特点
reeco
2022-09-18 00:10:28 +08:00
这有啥难的
nuk
2022-09-18 23:22:39 +08:00
excel 写的时候有缓存,xml 构造不会慢,所以瓶颈是 mysql 读,而多线程读 mysql 肯定是更快的,所以这其实就是 MPSC 的问题。
YepTen
2022-09-19 08:48:55 +08:00
我怎么感觉面试官是在问怎么把数据库数据写成 Excel 文件。其他语言不知道,但 java 写 Excel 之前是 POI ,这玩意可耗内存啊,之后是用阿里的 EasyExcel 。50W 的数据对数据库来说不是毛毛雨,直接读就是了。问题应该是在如何写,而不是读。
YepTen
2022-09-19 08:53:58 +08:00
如果现在问这个问题,限定 Java 的话,就是直接读+EasyExcel 。一个方法里就写完了,我写过 100 万的数据到 Excel 表里,一点问题没有。

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

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

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

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

© 2021 V2EX