极速响应Excel数据报表请求的一种方法
摘要
通过缓存和维护Excel Workbook实例,极速响应Excel数据报表请求。
这是一个真实的大数据“云计算”项目中的解决方案,在给定的时间和资源下,只有这种方法是最简单并且是可行的。
XX公司的需求
简单Excel报表:1个sheet。5秒内可以在界面展示。
复杂Excel报表:7个sheet。20秒内可以在界面展示。
并发响应:20个用户
详细介绍
每个sheet中有大量的Excel公式,如 F=E32-[35764%D1]*[DD]/[LD]。
每个单元格的值,需要后台从Mongodb数据库中取出并计算。
Web前端获得后台返回的数据,插入到Excel单元格中,然后Excel自动执行公式,然后将Excel完整地显示到界面中。
时间瓶颈
后台数据获取和数据计算的时间:
1个sheet要3-4s,7个sheet要10到20s。
前台展示剩下的时间:
1个sheet:1到2秒
7个sheet:0到10秒
读取Excel文件需要的时间
1个sheet:1s左右
7个sheet:2s左右
Excel文件构造成POI XSSFWorkbook对象
1个sheet:1s左右
7个sheet:7s左右
最初,我以为是IO有瓶颈,后来发现不是。主要是POI 构造XSSFWorkbook对象,需要花费很长时间。
XSSFWorkbook这可是一个比较大且复杂的数据结构,维护着一个Excel文档的所有信息。
(令人可气的是,测试机Linux服务器性能竟然还不如我的笔记本)
解决方案
考虑到并发请求最多也就是20,而且这只是一个Demo项目,因此“空间换时间”是可行的。
灵感来源:数据库连接池、对象池、缓存等都可以用来提高程序的性能。
最终方案:维护一份Workbook资源池。程序启动后,写一个定时器,监控资源池中的对象数量,达到资源下界的时候,就构造一些新的对象放进资源池中。
与数据库连接池等不同的是,Workbook资源池中的每一个XSSFWorkbook对象,只能使用一次。用完后,就必须从资源池中删除。
因为,XSSFWorkbook被使用后,很多状态都变了。
资源池代码结构
public class WorkbookPool {
private static int complexMinSize = TemplatePropertyReader.COMPLEX_MIN_SIZE;
// 复杂报表--最大缓存
private static int complexMaxSize = TemplatePropertyReader.COMPLEX_MAX_SIZE;
public WorkbookPool() {
}
public void init() {
simpleReportTimer();
complexReportTimer();
}
// 定时器任务---创建报表对象
private void simpleReportTimer() {
log.info("Simple Producter Timer Start...");
Timer producterTimer = new Timer();
// 在1秒后执行此任务,每次间隔1秒
producterTimer.schedule(new SimpleProducterTask(), 1000, 1000);
}
private void complexReportTimer() {
log.info("Complex Producter Timer Start...");
Timer complexProducterTimer = new Timer();
// 在1秒后执行此任务,每次间隔1秒
complexProducterTimer.schedule(new ComplexProducterTask(), 1000, 1000);
}
// 简单报表--定时器任务
class SimpleProducterTask extends TimerTask {
public void run() {
int simpleSize = simpleVector.size();
if (simpleSize <= simpleMinSize) {
int toBuildSize = simpleMaxSize - simpleSize;
log.info("before : simpleSize=" + simpleSize + ",toBuildSize=" + toBuildSize);
buildSimple(toBuildSize);
log.info("after : simpleSize=" + simpleVector.size());
}
}
}
// 复杂报表--定时器任务
class ComplexProducterTask extends TimerTask {
public void run() {
int complexSize = complexVector.size();
if (complexSize <= complexMinSize) {
int toBuildSize = complexMaxSize - complexSize;
log.info("before: complexSize=" + complexSize + ",toBuildSize=" + toBuildSize);
buildComplex(toBuildSize);
log.info("after: complexSize=" + complexVector.size());
}
}
}
}
启示
数据库连接池、对象池、缓存等很多程序设计中的概念,是存在着相似之处的。
学习和借鉴每一个成熟的概念和解决方案,能够产生更多的好方法。
活学活用,灵活解决实际工作中遇到的问题。
拒绝码农,谢绝书呆子。
相关阅读
ExcelToHtmlTable转换算法:将Excel转换成Html表格并展示(项目源码+详细注释+项目截图)
码农:客户是恶魔
原文参见:http://FansUnion.cn/articles/2851 小雷网(FansUnion.cn)
极速响应Excel数据报表请求的一种方法的更多相关文章
- SqlServer表EXCEL数据复制的另一种方法
一个.SqlServer表中的数据复制到excel 1.新建查询,用sql语句把表数据读出来 2.然后,选择数据,右键.复制(也能够点击连同标题复制),拷贝到记事本中(不然会乱码) 3.然后再把记事本 ...
- php发送post请求的三种方法示例
本文分享下php发送post请求的三种方法与示例代码,分别使用curl.file_get_content.fsocket来实现post提交数据,大家做个参考. php发送post请求的三种方法,分别使 ...
- php发送get、post请求的6种方法代码示例
本文主要展示了php发送get.post请求的6种方法的代码示例,分别为使用file_get_contents .fopen.fsockopen.curl来发送GET和POST请求,代码如下: 方法1 ...
- DataTable数据批量写入数据库三种方法比较
DataTable数据批量写入数据库三种方法比较 标签: it 分类: C#1) insert循环插入:2) sqldataadapter.update(dataset,tablename); ...
- 【MySQL】锁——查看当前数据库锁请求的三种方法 20
MySQL提供了查看当前数据库锁请求的三种方法:1. show full processlist命令 观察state和info列 2. show engine innodb status\G ...
- 手机数据抓包的N种方法
手机数据抓包的N种方法 - xia_xia的博客 - 博客频道 - CSDN.NEThttp://blog.csdn.net/xia_xia0919/article/details/50606137 ...
- DataTable 数据批量写入数据库三种方法比较
DataTable数据批量写入数据库三种方法比较 1) insert循环插入: 2) sqldataadapter.update(dataset,tablename); 3) sqlbul ...
- 使用命令行将Excel数据表导入Mysql中的方法小结
从Excel数据表导入MySQL,已经做过好几次了,但每次都会碰到各种问题:invalid utf8 character string, data too long, ...,浪费了不少时间 为了提高 ...
- 【MySQL笔记】Excel数据导入Mysql数据库的实现方法——Navicat
很多公司尤其有点年头的公司,财务业务部门的各种表单都是excel来做的表格,随着互联网的发展各种业务流程都电子化流程化了,再在茫茫多的文档中去查找某一个年份月份的报告是件相当枯燥的事,所以都在想办法将 ...
随机推荐
- C++之const关键字
本文引自http://www.cnblogs.com/lichkingct/archive/2009/04/21/1440848.html ,略有增删 const关键字在c++中用法有很多,总结如下: ...
- 利用SQL索引提高查询速度
1.合理使用索引 索引是数据库中重要的数据结构,它的根本目的就是为了提高查询效率.现在大多数的数据库产品都采用IBM最先提出的ISAM索引结构. 索引的使用要恰到好处,其使用原则如下: 在经常进行连接 ...
- [NOI2014]动物园(KMP)
题意 题解 因为,一直用j=nxt[j]来遍历,可以遍历前i个字符所有相等的前后缀长度,所以有一个暴力的想法,就是对于每一个长度,开始遍历,记录长度小于i/2的相等的前后缀数量,最后累加即可. 但显然 ...
- python+selenium进行简单验证码获取
# _*_ coding:utf-8 _*_from PIL import Imagefrom selenium import webdriverimport pytesseractimport ti ...
- Camera Calibration 相机标定:原理简介(五)
5 基于2D标定物的标定方法 基于2D标定物的标定方法,原理与基于3D标定物相同,只是通过相机对一个平面进行成像,就可得到相机的标定参数,由于标定物为平面,本身所具有的约束条机,相对后者标定更为简单. ...
- 小于等于N的全部整数与N关于gcd(i,N)的那些事
相关问题1: 求小于等于N的与N互质的数的和.即∑ i (gcd(i,N)=1, N>=i>0) 依据N的规模能够有非常多种方法.这里我介绍一个比較经典的方法 先说下这个结论:假设 gcd ...
- 作为一个程序员怎么通过android开发赚钱
上面是一个程序员通过Android开发每天的收入,信则有! 自己学安卓差不多,有一年了.我本来是从事javaweb开发的,可能学习安卓上手会快点.其实安卓没有那难 .首先开发安卓程序,要有一个,开 ...
- [MST] Remove Model Instances from the Tree
In this lesson we will dive a bit more into the tree semantics of MST. In this lesson you will learn ...
- C++ Primer笔记13_运算符重载_总结
总结: 1.不能重载的运算符: . 和 .* 和 ?: 和 :: 和 sizeof 和 typeid 2.重载运算符有两种基本选择: 类的成员函数或者友元函数, 建议规则例如以下: 运算符 建议使用 ...
- 教你怎样做个有“钱”途的測试project师
百度百科说測试project师这一职业的待遇,薪酬上升空间很大.但測试project师也有自己的烦恼,比方在程序出错后,将问题反馈给程序猿,然后程序猿给的答复是:"oh,howisthatp ...