JDBC 连接 Oracle 时,用 rs.absolute(n) 真的不如 n 次 next() 性能好

前面写过一篇:Oracle 驱动版本引起的显示字段奇怪编码问题。讲到因 Oracle 8.0.5 不支持子查询排序,为改善原来那种每次翻页时都捋出所有数据成对象到 List 中,然后从中拣取页面实际要显示的记录的性能问题时,采用了 rs.absolute() 直接跳到起始记录游标的方法,但又引入了乱码问题,例如:"无效",变成了 "0xE697A0E69588"。

虽说,换个驱动,如 8.1.7.0.0 以上版本的驱动就能解决乱码的问题,但这一换又怕会影响到其他的应用。有朋友评论说,其实循环 next() 到某处比 absolute() 定位要好,乍一看,有些牵强,不过试试就知道了。下面就来做样一个测试,测试代码如下:

测试环境:
Oracle 数据库 8.0.5.1.0
驱动文件:classes12.zip
驱动版本:8.1.6.0.0
驱动类:oracle.jdbc.driver.OracleDriver

测试数据(未列出每一次的测试数据,只求了不同条件下的平均值,startCuror 为定位的游标位置,stepByStep 表示是用 n 次 next() 移动游标,还是用 absolute(n) 直接定位,true 为前者):

 
游标定位平均耗时

获取数据平均耗时
 
游标定位平均耗时

获取数据平均耗时
 1 条件:startCursor = 1000; stepByStep = true;   条件:int startCursor = 1000; stepByStep = false;
  161.222 毫秒 1547.111 毫秒   183.889 毫秒 1670.333 毫秒
           
 2 条件:startCursor = 10000; stepByStep = true;   条件:startCursor = 10000; stepByStep = false;
  1445.25 毫秒 1541.667 毫秒   1532.667 毫秒 1717.417 毫秒
           
 3 条件:startCursor = 100000; stepByStep = true;   条件:startCursor = 100000; stepByStep = false;
  11719.17 毫秒 1225.333 毫秒   11894.67 毫秒 1290.25 毫秒
           
 4 条件:startCursor = 500000; stepByStep = true;   条件:startCursor = 500000; stepByStep = false;
  56653.83 毫秒 1225.083 毫秒   java.lang.OutOfMemoryError: Java heap space

换着用 8.1.7.0.0, 9.0.1.1.0 这两个版本的驱动,和连接到 9.2.0.1.0 版本的数据库测试得出来的数据都相仿。由测试数据大致可以得出如下结论:

1. 用 absolute(n) 比循环 n 次 next() 定位游标的时间要稍长,但不是很明显。也许这只是跟  ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY 类型的 Statement 有关。

2. 创建了 ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY 类型的 Statement 时,取数据记录的时候也会慢一些,也不是很明显。

3. 但最后一点是始料未及的--居然产生了内存溢出。移动游标到 500000 的位置时,用 next() 循环没问题,用 absolute 无论是连接 Oracle 8.0.5.1.0 还是 Oracle 9.2.0.1.0 时均告 OutOfMemoryError。可见 absolute,或者是 ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY 类型的 Statement 占用内存会比较大。看起来似乎真的在执行 absolute(n) 方法的时候预读了数据到内存中。

前面一直是关注 absolute(n) 和 n 次 next() 的速度问题,未考虑到 Statement 本身类型的问题,所以还需看看对 ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY 类型的 Statement 进行 n 次 next() 效果,会如何,是否在 500000 次 next() 也会像 absolute(500000) 那样产生 OutOfMemoryError 堆内存溢出异常,这还有待于求证。

 

本文链接 https://yanbin.blog/jdbc-oracle-rs-absoluten-or-next-n/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments