Fork me on GitHub

【疑难杂症02】ResultSet.next() 效率低下问题解决

  今天帮同事解决了一个问题,记录一下,帮助有需要的人。

一、问题解决经过

  事情的经过是这样的,下午我在敲代码的时候,一个同事悄悄走到我身边,问我有没有用没用过Oracle,这下我蒙了,难道我在他们眼中这么弱吗?不过我还是弱弱的问了一句咋了,他说碰到一个奇怪的现象,说他用jdbc查询Oracle,然后循环取数据要30秒,我问怎么可能,他说是真的,就1000条数据,我当然不信,就说带我去看。

  然后我走过去,发现他旁边还坐了一个人,我猜也在帮忙解决问题,只不过没有解决而已,我让他给我看看代码,我看了一眼,发现很简单,如下(只是示例代码,真实代码不便贴出):

Connection conn = getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
long start=System.currentTimeMillis();
while(rs.next()){
    //一系列操作
}
System.out.println(System.currentTimeMillis()-start);
=========控制台输出==========
大约就是30秒以上

  我一看,这不是标准的jdbc操作吗,我都写了800遍了,怎么可能会有问题,有问题也只能是SQL问题,于是我说给我看看你的SQL,我觉得你写的SQL有问题,结果他说不可能,SQL没有问题,而且我刚刚打断点一步一般走下去都很快,就是next()方法耗时30多秒的,旁边那位依然也说不可能是SQL的问题,SQL都看了,然后我又说了一遍,给我看看你写的SQL,结果还是说SQL肯定没问题,旁边那位甚至说出了让我惊讶的话,他说是不是ResultSet 的next方法有问题,你快去网上找找有没有其他的替代方法。

  此时我心中一万只草泥马奔腾而过,我看过一些源码,而且知道操作数据库的底层都是封装的它们,旁边这位不仅不解决问题,还打算掩埋问题绕弯路,我想说你把我叫过来解决问题,能不能听我的,不过我没有这么说,因为他们两个都是我的领导,要不是喊我过来的那个我和他关系很好,我早就回去不管了。

  不过在我的再三请求下还是给我看了SQL,我一看很长,我就说拿到PL/SQL中执行一下,结果又来否定我,说我都执行过了很快的,旁边那位依然大声说怎么可能是SQL问题呢,以前就用过了,我只能说我心好累,最终放到PL/SQL中执行了,结果确实是两三秒显示出来,他们就说你看。

  我什么也没说,大家应该都知道PL/SQL执行后只会显示前多少条数据,只有点向下的箭头才会显示所有的数据,我就让他显示所有的数据,因为只有1000条我想是很快的,确实剩下的飞快的显示完,但是当显示完1000条数据以后,执行并没有终止,直到30多秒过去以后,才显示执行完成,也就是说查询出需要的1000条数据后,查询依然进行只是没有输出结果。

  我说你SQL写的有问题,结果在这种情况下,他居然还说,那刚刚那条语句怎么飞快的执行完了呢:

ResultSet rs = stmt.executeQuery(sql);

  说这条执行完了,不就把所有的结果都带回来了吗,说实话我没有深入了解过,不过我猜应该是没有带回来,我让他测试一下,取所有数据大约5W条,ResultSet 依然很迅速的获取到,但是按常理是不会这么快的,结合刚才的现象猜测,ResultSet 并没有带回来结果集。

  然后我又看了一遍他写的SQL,看出了问题,分页写错了,我说你改好应该就没有问题了。

二、收获总结

2.1 我的收获

  帮别人解决问题还是有收获的,首先可以肯定的事是ResultSet.next() 效率低下是错觉,真正效率低下的是写出SQL的执行速度,同样ResultSet只是代表着结果集,而不表示它就是整个结果集的数据,具体源码等我有空的时候会研究并贴出。

2.2 我想说的话

  当出现奇怪的问题的时候,不要这么做:

  1. 大量重复测试
  2. 怀疑框架,怀疑Java,怀疑人生

  这两条是很重要的,大量重复测试是大忌,浪费时间而且还容易掩盖错误,一遍遍看着结果露出不可置信的眼神,第二条就是怀疑Java是不是有缺陷,框架是不是有bug,当然不可否认任何东西都不是完美的,但是相比较而言,还是首先怀疑自己比较好。把自己理所当然觉得没问题的步骤好好看一遍,也许原因就在其中。

 

posted @ 2017-06-27 21:36  已往之不谏  阅读(3846)  评论(3编辑  收藏  举报