JqGrid大数据集加载性能优化咨询(Java Spring MVC + Intramart环境)
JqGrid大数据集加载性能优化咨询(Java Spring MVC + Intramart环境)
我看了你的问题和代码,现在加载几千条数据要2分钟确实太影响用户体验了,核心问题应该是你当前用的是前端假分页——不管用户看第几页,后端都一次性把所有符合条件的数据查出来、处理完再传给前端,大数据量下数据传输、内存占用、前端渲染都会慢到爆炸。下面给你几个针对性的优化方案,都是结合你的代码和使用环境来的:
1. 先搞真正的服务器端分页(最关键!)
你现在的Repository方法是一次性查出所有数据,哪怕前端有分页控件,也只是把全量数据拿到前端后再切分,这在数据量大的时候完全行不通。得改成后端只返回当前页需要的数据:
- 修改Repository方法:新增分页参数
pageNum(当前页码)和pageSize(每页条数),SQL里加上数据库对应的分页语法(比如MySQL用LIMIT offset, pageSize,Oracle用ROWNUM),同时还要查询符合条件的总记录数,这样前端jqGrid才能知道总页数、总条数。
比如你的SQL最后可以这么加:
还要单独写一个统计总记录数的SQL(WHERE条件要和数据查询的完全一致),最后把总条数、当前页数据、总页数一起返回给前端,比如用Map封装成int offset = (pageNum - 1) * pageSize; sql += " LIMIT ?, ?"; parameters.add(offset); parameters.add(pageSize);{ "total": 总页数, "page": 当前页, "records": 总条数, "rows": 当前页数据 }的结构。 - 前端配置调整:确保你用的imui:listTable(基于jqGrid)开启服务器端分页,配置
rowNum(默认每页条数)、rowList(可选条数),并且让它把分页参数(page、rows)传给后端。Intramart的imui组件应该有对应的属性配置,比如serverPaging="true"这类,你可以查下官方文档确认。
2. 优化数据库查询速度
数据库查询是性能瓶颈的重灾区,你的代码里有几个可以快速优化的点:
- 别用
SELECT *,只查需要的字段:你最后在Java层只用到了模型的部分字段,SQL里直接列出来这些字段,比如SELECT doc_type, plant_code, gr_doc, ... FROM v_gr_list_w_price_v2,减少视图返回的数据量,既省内存又省传输时间。 - 给查询字段加索引:你的查询条件用到了
tr_type、gr_date、gr_doc、vendor_code这些字段,如果有排序需求的话,排序字段也得加索引。先检查下v_gr_list_w_price_v2视图的底层表,这些字段有没有建索引,没有的话赶紧加,能大幅加快查询速度。 - 把Java层的计算移到SQL里:你现在在循环里计算vat_rate、vat_amount这些值,能不能把vat_master的数据关联到查询中,直接在SQL里算出这些结果?这样就不用在Java层循环处理每条数据,能省很多时间。
3. 优化Java层的处理逻辑
你的Java代码里有几个拖慢速度的细节,调整后能明显提升效率:
- 批量获取vat数据,别循环调用接口:你现在在循环里每次调用
invoicingWorkflowService.getItem(maxDate),几千条数据就会调用几千次,这肯定慢死了!应该先把所有需要的maxDate收集起来,批量调用接口获取所有vat数据,然后存到一个Map里,循环的时候直接从Map里取,比如:// 先收集所有需要的maxDate Set<String> needMaxDates = new HashSet<>(); for (InvoicingGRListModel model : sqlResults) { Integer grDate = Integer.parseInt(model.getGr_date()); int maxDate = findMaxDate(validfromArray, grDate); needMaxDates.add(Integer.toString(maxDate)); } // 批量获取vat数据 Map<String, Item> vatItemMap = invoicingWorkflowService.getItemsByCodes(needMaxDates.toArray(new String[0])); // 循环时直接从map取数据 Item item = vatItemMap.get(Integer.toString(maxDate)); - 避免循环里重复创建对象:比如
DecimalFormat可以提到循环外面,不用每次循环都新建;BigDecimal的计算尽量复用对象,减少内存开销。
4. 前端小优化
- 确保jqGrid的
loadonce设为false(默认就是),这样每次分页、排序、搜索都会请求服务器,只加载当前页数据。 - 搜索功能保持在服务器端处理,别把全量数据拿到前端再过滤,你现在的前端点击按钮后再请求的逻辑是对的,继续保持。
按这些方法改完,加载速度应该能从分钟级降到秒级,甚至更快。
备注:内容来源于stack exchange,提问作者Lily
相关产品推荐
相关产品推荐

