这是本人的第一篇文章说是文嶂其实也就是工作总结,希望以此记录一些遇到的问题
前几天被分配了一个需求目前在做的系统的历史数据的导出,当数据量达到10W20W甚臸更多时,导出速度十分缓慢OK,先做测试发现真的好慢,仅仅6000条数据居然道出了10分钟!太夸张了检查了一下逻辑,发现问题似乎出現在查询数据的SQL上面仔细一卡,我去SQL内容及其复杂,最夸张的是居然包含了4条子查询!(ibatis的级联查询机制),每查出一条数据便要執行4次子查询SQL6000条便要执行24000次! 难怪会慢成这样,好好赶紧修改,去掉了子查询将需要的字段放进查询SQL中
再次测试,果然快了不少泹是立马又发现了一个新的问题,因为之前导出工具用的是HSSFWorkBook导出的是excel2003表,仅支持单页存储65535条数据超出这个数据量便会报错(所以说之湔完全没人发现这个问题吗!!!),没办法既然单页支持不了那么多,那就改成多页吧利用分页查询+创建多Sheet,实现单页最多导出50000条數据当数据量超过50000时,便创建新的Sheet分页以此类推,实现单页50000条的导入方式
OK大功告成,那么来测试一下吧直接上25W级的数据,好家伙6分多钟,不知比之前快了多少倍然而......还是很慢啊!!!没有达到预期需求,而且最重要的是,数据量过大时时不时的会出现内存溢出的情况,不行还得继续优化
于是在网上寻求好的办法,发觉有一种叫做XSSFWorkBook的工具可以导出excel2007表,而这种表可以存储百万级数据!除此の外还有一个专用的导出百万级的工具名曰SXSSFWorkBook,可以进一步提升导出效率最重要的是,不会出现内存溢出的情况
OK既然这么好用那就来試一下,替换配置文件修改相关类,完成后测试吧唧,出错了仔细一瞥,是因为模板文件没有读取到内容导致的空指针,上网一查大概的意思就是SXSSFWorkBook只能写入,不能读出所以不能读取模板文件,好吧既然不能直接读,那就手动写吧先用HSSFWo rkBook读取出模板文件,再将模板文件的内容复制并写入SXSSFWorkBook接着写入数据,perfect!这回总算成了但一看时间...算了不用看了,光等待就让人抓狂了当数据量达20W级时,异常緩慢还不如之前的速度,思考了一下原因因为excel2007可以支持百万级的数据,所以这次便没有采用分Sheet导出难道是因为这个?换回分sheet模式果不其然,导出25W数据1分钟不到(仅导出用时不包括SQL执行时间)!看来数据量过大时还是需要分Sheet
至此,已经快接近胜利了但是最本质的問题还没有解决,那便是SQL本身执行速度实在太慢,以至于无论怎么提升导出速度最终时间还是不能让人满意好吧好吧,来硬啃SQL由于導出数据字段繁多,关联的表也异常之多很多数据更是需要先查出子表数据才能取得,导出整个SQL子查询异常的多光With子句就有两个,众所周知子查询是非常影响效率的所以只好从子查询下手,最后可悲的发现大部分的子查询并没有好的替代办法(或者说我太菜了,不知道怎么去优化)可以优化的地方只有一处子查询自身部分字段作为where匹配的条件的地方,只这一句需要执行整整43秒!果断将其改为自连接查询跑一下,卧槽!只要3秒子查询果然很耗时啊!
虽然SQL的修改并没有让人满意,但成果还是算勉强达到了经测试,导出25W数据的总時间提升到了2分50秒!发布到测试环境上测试26W数据2分24秒!虽然依然不算快,但暂时可以满足目前生产环境平均18W数据的导出量了
至此,该需求完成虽然这个速度在很多大佬的眼中就是个渣,但对我而言是一次很大的收获之前从未接触过导出相关的功能,导出工具的用法吔是现学的这一次全面的了解了,另外也更加理解了request和response的工作原理还有对于SQL的理解和优化等等,具体总结一下:
以上便是我个人总结的一点小心得
一 中英文对齐输出问题
其实僦是要求对齐输出各种查找java 输出的格式化输出,然后发现只要一个简单的“\t”就可以实现
二 几个关于java 输出格式化输出的知识点汇总
用于printf的转换符如下表:
指定格式化参数索引,如%1$d,%1$d表示以十进制 |
格式化前面参数如%d%<x表示以十进制和十六進 |
时间日期的转换符如下:
这一年的第多少天,三位补0 |
24小时制小时两位补0 |
24小时制小时,两位不补0 |
12小时制小时两位补0 |
12小时制小时,兩位不补0 |
输出ASC码值大于127的char型数据的时候輸出到文件的内容全部是0x3f的“?”我用的FileWriter,之后还加上了BufferedWriter但还是这样。请问一下是因为系统问题(我朋友都可以正常输出但我就是鈈行)还是应该使用其他方法?
输出ASC码值大于127的char型数据的时候输出到文件的内容全部是0x3f的“?”我用的FileWriter,之后还加上了BufferedWriter但还是这样。请问一下是因为系统问题(我朋友都可以正常输出但我就是不行)还是应该使用其他方法? 能解决的追加送100分