使用适用于 Oracle 的 JDBC 迭代 ResultSet 需要花费大约 16 秒的大量时间?

2022-09-02 14:25:46
while( result_set.next() )
{
  ...
}

我已经使用并计算了时间,对于每次迭代,花费的时间以毫秒为单位,但整个循环大约需要16s。我正在考虑一个可能的原因,即条件测试需要花费大量时间,即功能。System.nanoTime()next()

仅供参考,我正在连接到远程数据库服务器,并且我所做的选择查询在毫秒内完成,再次使用上述方法计算。关于为什么会发生这种情况,以及我如何将迭代结果集的时间缩短到最大一秒的任何原因?

编辑:

我正在处理大约4000条记录,每条记录连接大约10列,每列的大小约为10个字符

编辑2感谢 setFetchsize() 做了魔术, 真棒, 真棒


答案 1

我设置了一个包含 4000 行和 10 列(每列包含 10 个字符)的表,并使用以下方法进行了简单的性能测试(是一个测量 和 之间实时时间的类):RealTimeCounterstart()stop()

List<String> myResult = new ArrayList<>();
ResultSet rs = s.executeQuery("SELECT * FROM Performance");

RealTimeCounter rtc = new RealTimeCounter();
rtc.start();
while(rs.next()) {
    myResult.add(rs.getString(1));
}
rtc.stop();
System.out.println(rtc);

结果:

  • 默认抓取大小:执行时间约为 20 秒
  • 提取大小 = 100:执行时间约为 2.2 秒
  • 提取大小 = 500:执行时间约为 450 毫秒
  • 读取大小 = 2000:执行时间约为 120 毫秒
  • 提取大小 = 4000:执行时间约为 50 毫秒
  • 提取大小 = 4001:执行时间约为 10 毫秒 (!!)

因此,读取大小确实对执行速度有重大影响。


另一方面,读取大小对内存消耗有一定影响。有趣的是,使用上述代码之前和之后的快速分析表明,影响比我预期的要小得多。我得到的数字是:Runtime.getRuntime().freeMemory();

  • 默认抓取大小:665k
  • 提取大小 = 100: 665k
  • 提取大小 = 500: 665k
  • 提取大小 = 2000: 743k
  • 提取大小 = 4000: 821k
  • 提取大小 = 4001: 861k

答案 2

尝试更改结果集提取大小。默认情况下,Oracle JDBC 驱动程序一次仅从数据库游标接收 10 行结果集。它可能不会显着提高性能,但没有很多其他选项可以使驱动程序更快地工作。


推荐