转 大数据量下载解决方案

本文探讨了在处理大数据量时,因时间超时和内存溢出引发的问题。针对这些问题,提出了分页接口、使用数据流(CSV格式)以及HTML方式导出数据的解决方案。通过实践验证,CSV和HTML方式在内存管理和效率上有优势,适合大数据量下载。建议在数据量超过10000行时,切换新的工作表以避免Excel行数限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

]

 

问题描述:              

最近遇到一个很棘手的问题,信用卡网上支付的交易越来越多了,日平均交易数量很大,并且这个数据还处在一个上升的阶段,但这仅仅是个开始。我们这边的系统负责给柜员提供一系列报表,数据量比较大,时不时的会time out,或者会om掉。

原因分析:

Time out超时现象:这个是我们系统跨另外一个系统获取数据,我们所用技术的框架有个超时设置,即一般不能超过60秒。这样设置也合情合理,换作我是客户,我也不愿意在页面提交个请求后,要等很长时间才给我个结果。

这个问题瓶颈在于我们访问后台的时间瓶颈,即我们不能耗时太长,也就是说根本不可能要求修改框架设定的超时时间。

那么怎么解决呢?我们只有要求后台分批返回这些数据。

Outof Memory内存溢出现象:这个问题是当数据量比较大的时候,下载时这些大数据占用太多内存,JAVA虚拟机报出的错误。有个直接的但不长久的解决方法,就是增大JAVA虚拟机的内存设置,但随着数据量的增长,这个解决方法就会被淘汰。

解决方案分析:

Time out问题可以和提供接口方商讨,按照分页的方式即可解决。

我们重点关注一下OM的问题吧。这里有几种解决方案:

1.      用POI或JXL

POI是apache公司的一个子项目,主要提供一组windows文档的Java API;

JXL是Java Excel的简称,一个开放源码的项目,通过它Java开发人员可以操作Excel        文件的内容,可能它更专注些,比如名字就叫做java(不包含其他编程语言)的excel(不处理windows的其他文件),所以数据量稍大时效率以及在消耗内存方面,略胜前者一筹,这里我就不再赘述两者之间的差别了,在网络上大家可以搜索到一大箩筐关于此信息。

数据量
 POI/JXL
 加载时间(ms)
 总耗时(ms)
 
 

1千条:746K

 
 POI
 499
 515
 
JXL
 203
 359
 
 

1万条:7.3M

 
 POI
 1716
 1731
 
JXL
 390
 1108
 
 

5万条:36.8M

 
 POI
 7878
 7925
 
JXL
 2309
 5711
 

 

我们来说说稍微好些的插件JXL的处理方式,JXL是将每个单元格生成一个Cell对象,每一个对象都要消耗一定的内存空间,每个对象的大小不同,也会影响内存的使用,所以很容易导致内存溢出。

2.用数据流的方法

从消耗内存的原因出发,既然上述表现较好的JXL由于生成大量的对象导致,我们就采用避免java创建太多的对象,就不用jxl了。用数据流的方法解决。

可以直接写txt文本文件,可以用”/t”来分割内容的话,用户就可以直接把txt生成的内        容直接复制到excel中去。

也可以用流的方式写成.csv格式,写入方式和写txt文件类似,可以用流的方式追加,只要在每列之间以固定标示符进行间隔,不存在内存和格式问题。这种格式可以让用户直接以exl方式打开,而不用复制进去了。

3.HTML方式

其实我们就是用页面元素的属性设置,来达到和xls相互转换,所以可以先写HTML,这样内存不会溢出,写好后,用xls方式打开即可。

不妨你可以试一试,打开一个xls,选择另存为网页,可以查看下这个经过转换后的html的源码,直接把这个HTML文件后缀改为xls,打开后效果和刚刚的那个xls一样。  

 

这种方式正是我们现在项目所采用的方式,但我们采用的是jsp默认的输出数据到页面,并没有通过java的io程序来实时控制,当数据量比较大的时候,进行适当的flush。所以目前的项目中这种方式,也存在着潜在的OM的可能。

 

实践验证:

数据流方式csv生成:

public class CSVUtils {

    /** 

     * 导出为CVS文件    

     * @param exportData 

     */ 

    public static File createCSVFile(List exportData, LinkedHashMap rowMapper, String outPutPath) {  

        File csvFile = null;  

        BufferedWriter csvFileOutputStream = null;  

        try {  

            csvFile = File.createTempFile("temp", ".csv", new File(outPutPath));  

            // GB2312使正确读取分隔符","  

            csvFileOutputStream = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile), "GB2312"),  

                    1024);  

            // 写入文件头部  

            for (Iterator propertyIterator = rowMapper.entrySet().iterator(); propertyIterator.hasNext();) {  

                java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator.next();  

                csvFileOutputStream.write("/"" + propertyEntry.getValue().toString() + "/"");  

                if (propertyIterator.hasNext()) {  

                    csvFileOutputStream.write(",");  

                }  

            }  

            csvFileOutputStream.newLine();  

            // 写入文件内容  

            for (Iterator iterator = exportData.iterator(); iterator.hasNext();) {  

                Object row = (Object) iterator.next();  

                for (Iterator propertyIterator = rowMapper.entrySet().iterator(); propertyIterator.hasNext();) {  

                    java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator.next();  

                    csvFileOutputStream.write("/"" 

                            + BeanUtils.getProperty(row, propertyEntry.getKey().toString()).toString() + "/"");  

                    if (propertyIterator.hasNext()) {  

                      &n

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值