50k行数据下将javax.servlet.jsp.jstl.sql.Result转换为String列表过慢,求优化方案
优化从
Result中提取字符串列表的速度 哇,50k行数据循环耗时30秒确实够闹心的!咱们从原代码的瓶颈入手,一步步给出优化方案,都是不需要修改查询逻辑就能实现的:
1. 预缓存Rows数组,减少重复方法调用
原代码每次循环都调用result.getRows()[i],虽然getRows()可能只是返回内部数组,但反复调用方法会带来额外的开销。先把数组存到局部变量里,局部变量的访问速度远快于对象方法调用:
String internalIdString = "INTERNALID"; // ... 省略查询代码 ... Result result = queryResult.getResult(); // 预取整个rows数组到局部变量 SortedMap<String, Object>[] rows = result.getRows(); m_InternalIds = new ArrayList<>(rows.length); for (int i = 0; i < rows.length; i++) { m_InternalIds.add((String) rows[i].get(internalIdString)); }
2. 用列索引替代列名取值(最有效的优化)
原代码通过SortedMap.get(列名)取值,而SortedMap的get操作是**O(log n)复杂度(比如底层是TreeMap),50k次循环下来累计开销极大。我们可以先找到目标列的索引,再用Result.getColumnValue(行索引, 列索引)直接取值——数组访问是O(1)**复杂度,能大幅提升速度:
String internalIdString = "INTERNALID"; // ... 省略查询代码 ... Result result = queryResult.getResult(); // 第一步:找到目标列的索引 int targetColumnIndex = -1; String[] columnNames = result.getColumnNames(); for (int j = 0; j < columnNames.length; j++) { if (internalIdString.equals(columnNames[j])) { targetColumnIndex = j; break; } } if (targetColumnIndex == -1) { // 处理列不存在的异常情况 m_InternalIds = new ArrayList<>(); return; } // 第二步:通过列索引批量提取值 int rowCount = result.getRowCount(); m_InternalIds = new ArrayList<>(rowCount); for (int i = 0; i < rowCount; i++) { m_InternalIds.add((String) result.getColumnValue(i, targetColumnIndex)); }
3. 尝试并行流处理(利用多核CPU)
如果你的服务器是多核的,可以用Java Stream的并行模式来加速数据转换,适合CPU密集型的转换场景:
String internalIdString = "INTERNALID"; // ... 省略查询代码 ... Result result = queryResult.getResult(); SortedMap<String, Object>[] rows = result.getRows(); m_InternalIds = Arrays.stream(rows) .parallel() // 启用并行流 .map(row -> (String) row.get(internalIdString)) .collect(Collectors.toCollection(() -> new ArrayList<>(rows.length)));
注意:并行流适合数据量大的场景,如果数据量较小反而可能因为线程调度开销变慢。50k行的规模用并行流应该能看到明显提升。
为什么原代码这么慢?
原代码的核心瓶颈有两个:
- 反复调用
result.getRows()方法,增加了不必要的方法调用开销; - 每次从
SortedMap中按key取值,O(log n)的复杂度在50k次循环下被放大,累计耗时严重。
其中用列索引替代列名取值是效果最显著的优化,能直接把每次取值的复杂度从O(log n)降到O(1),预计能把循环耗时从30秒压缩到几秒甚至更短。
内容的提问来源于stack exchange,提问作者hobbes_child
相关产品推荐
相关产品推荐

