Oracle数据库大结果集ResultSet遍历速度过慢的优化方案咨询
优化Oracle ResultSet遍历慢的实用方案
嘿,我太懂你这种感受了——明明数据库查询秒出结果,结果遍历ResultSet的时候慢得像蜗牛爬,尤其是start 4那部分卡得让人着急。咱们来一步步解决这个问题:
为什么遍历会这么慢?
核心问题出在Oracle JDBC驱动的默认行为上:默认情况下,驱动每次只从数据库拉取10条数据到本地。你想想,50万条数据就得跟数据库做5万次网络交互,这来回的网络开销直接把速度拖垮了。另外你在循环里还频繁打印日志,同步IO操作也会雪上加霜,拖慢整体速度。
具体优化手段,按优先级来
1. 调整Fetch Size(最关键,立竿见影)
给PreparedStatement设置一个更大的fetch size,让驱动一次性从数据库拉取更多数据,减少网络往返次数。你可以根据自己的内存情况调整,比如设置成1000或者5000,甚至试试Oracle专属的优化参数:
PreparedStatement preparedStatement = con.prepareStatement(mayquery); // 普通设置,适合大多数场景 preparedStatement.setFetchSize(1000); // 或者Oracle专属优化:触发row prefetch机制,一次性拉取更多数据 // preparedStatement.setFetchSize(Integer.MIN_VALUE);
这个调整完,遍历速度会有质的提升。
2. 删掉循环里的打印操作
你现在每次循环都输出start 4 count:,50万次的同步打印操作非常耗时,完全没必要留着。如果需要看进度,可以改成每1万条打印一次,或者直接删掉,用日志框架的异步输出(比如Logback的异步appender)。
3. 优化后续存HashMap的操作(如果需要)
如果之后要把数据存HashMap,尽量避免用列名读取数据(比如resultSet.getString("column_name")),因为每次都要解析列名映射到索引,耗时。可以提前获取列的索引,循环里直接用索引读取:
// 提前获取列索引,只做一次 int idIndex = resultSet.findColumn("id"); int contentIndex = resultSet.findColumn("content"); HashMap<Integer, String> dataMap = new HashMap<>(); while (resultSet.next()) { Integer id = resultSet.getInt(idIndex); String content = resultSet.getString(contentIndex); dataMap.put(id, content); }
这样能进一步提升循环内的处理速度。
4. 内存不足时的备选方案:分批次处理
如果数据量实在太大,内存扛不住,可以考虑分页查询分批次处理,比如每次查1万条,处理完再查下一批。但这个是备选,先调fetch size基本就能解决大部分问题。
优化后的完整示例代码
String mayquery="select * from tablehistory"; try { System.out.println("# start 0"); PreparedStatement preparedStatement = con.prepareStatement(mayquery); // 核心优化:设置fetch size preparedStatement.setFetchSize(1000); System.out.println("# start 1"); ResultSet resultSet = preparedStatement.executeQuery(); System.out.println("# start 2"); int count =0; System.out.println("# start 3"); // 去掉循环内的频繁打印 while (resultSet.next()) { count++; // 这里加入存HashMap的逻辑,记得提前获取列索引哦 } System.out.println("# end a"); System.out.println("count:"+count); } catch(Exception e) { // 别吞异常,打印出来方便排查问题 e.printStackTrace(); }
内容的提问来源于stack exchange,提问作者Jacel
相关产品推荐
相关产品推荐

