β

大数据无小事

HelloMrKing 88 阅读

某某突然有个紧急的任务交给我处理,要求是把mysql的数据库表根据指定字段的值抽出一部分,处理一些字段后输出到文件,而且要控制输出文件的大小,同时要保证mysql不能太耗资源。心想so easy,二话不说马上开写了。

对于我这种完美主义外加强迫症,程序虽然小,也要达到最优。看了下公司的数据库,不管是哪个表,基本上都是10^9条记录以上,记录都有上百个字段。

想到几点:

1. 控制mysql消耗直接想到的是limit offset,count ,取数据和写数据是同步进行的,不需要一次性读取,循环查询,写入即可。

2. 虽然从mysql读取到内存,再写入到磁盘是一个标准的生产者消费者模型,能想到的就是BlockingQueue,在读写速度不太匹配的话,我还是不太敢用,说不定马上就OutOfMemory了,所以边读边写才是最好的。

rush好Java代码,测试。

服务器16核24G的内存,数据库所在的机器8核,84G内存。测试发现数据库完全不占cpu和内存,消耗太小,这应该是数据处理速度太慢,而我不到500行的小程序的几分钟后内存就从8%不断升高到16%,明显内存应该是基本恒定的值。

通过Netbeans自带的Profiler分析,占用内存较大的是byte数组,而年龄最大的几个对象基本不占空间,应该没有内存泄漏。

图片1

图片2

分析是最磨人的活:

若干小时后,找到了关键之处:在处理每行记录的时候new了一个String,这直接导致多一次内存复制,完全没有必要啊。处于循环最里层也加重了gc的负担。于是直接处理sql返回的ResultSet。

也发现了String的replace的效率太低,因为要考虑到正则表达式;StringBuilder的性能会好些,当然如果是简单的匹配替换最好还是自己写一个,而且应该是对char数组处理。

经过多次优化和测试(……),内存占用稳定在0.9%~1.1%,mysql的cpu稳定在200%,内存稳定在11%,不错,可以上线运行了,收工。

THE  END

作者:HelloMrKing
做一个简单快乐的程序员。
原文地址:大数据无小事, 感谢原作者分享。

发表评论