【疑难杂症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);

  我一看,这不是标准的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,当然不可否认任何东西都不是完美的,但是相比较而言,还是首先怀疑自己比较好。把自己理所当然觉得没问题的步骤好好看一遍,也许原因就在其中。

时间: 2024-08-02 02:46:37

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

关于"&"运算符效率低下的问题,有什么好的解决办法?

大家看看. 我们知道用" & "号比用"+"号快.因为"+"要对字符窜变量做类型判断并转换. 当时也没想出什么好办法.只是将两次"&"运算拆开,速度提了一倍.还是解决不了问题. 结果就是:for i 1 to 5000 ,i以字符形式相加.用&运算,要600-800ms 现在试试下面这个.建了个CStrCat的类. <% PageExeTime1=Timer * 1000 '计时开始 Set sc

解决 C++ 操作 MySQL 大量数据插入效率低下问题

往 Mysql 中,插入10000条简单数据,速度非常缓慢,居然要5分钟左右, 但是打开事务的话,一秒不到就搞定了 代码: #include <iostream> #include <winsock2.h> #include <string> #include "mysql.h" #pragma comment(lib, "libmysql.lib"); using namespace std; int main() { MYSQ

ORACLE使用WITH AS和HINT MATERIALIZE优化SQL解决FILTER效率低下

 在做项目的过程中,一个页面使用类似如下的SQL查询数据,为了保密和使用方便,我把项目中有关的表名和字段替换使用ORACLE数据库中的系统表和字段. 在我所做的项目中,类似ALL_TABLES的表中大概有8W多条数据,下面这个查询SQL很慢. WITH PARAMS AS (SELECT '' USER_ID, '' SDATE, '%' || '' || '%' SNAME FROM DUAL) SELECT AU.USERNAME, AU.USER_ID FROM ALL_USERS A

easyui-datagrid加载时的效率低下,解决方案

在360浏览器中 使用easyui  datagrid 加载数据是效率低下,有时候会出现卡机. 可以修改easyui源码进行解决.

MySql in子句 效率低下优化(亲测有效,从200秒变1秒)

MySql in子句 效率低下优化 背景: 更新一张表中的某些记录值,更新条件来自另一张含有200多万记录的表,效率极其低下,耗时高达几分钟. update clear_res set candelete=0 where resid in ( select distinct resourceid from att_attentionresult where important=0 ); 耗时 365s 优化后 update clear_res set candelete=0 where resi

利用反射将IDataReader读取到实体类中效率低下的解决办法

原文:利用反射将IDataReader读取到实体类中效率低下的解决办法 最开始使用反射一个类型的各个属性,对气进行赋值的代码如下: public static List<T> ToList<T>(IDataReader reader) { //实例化一个List<>泛型集合 List<T> DataList = new List<T>(); PropertyInfo[] properties = typeof(T).GetProperties()

效率低下?是管理者无能?还是“太宽容”?

效率低下,是当前许多企业都会面临的难题之一.一些企业甚至还会出现这样一种"神奇"的现象:老板和员工都在努力工作,公司上下几乎每个人都很忙,每个部门都忙不过来,但最终整体效率不仅没有很大的提升,反而还会降低. 很多人会将原因归结为是管理者的"无能".但实际上,导致效率低下的原因是多样的,从流程到制度.从监管到执行,任何环节出现问题,都会影响到实际的效果.企业效率低下,到底是管理者的"无能",还是"太宽容"? 为了提升效率,企业通

MySql in子句 效率低下优化

背景: 更新一张表中的某些记录值,更新条件来自另一张含有200多万记录的表,效率极其低下,耗时高达几分钟. update clear_res set candelete=0 where resid in ( select distinct resourceid from att_attentionresult where important=0 ); 耗时 365s 优化后 update clear_res set candelete=0 where resid in ( select reso

C++操作MySQL大量数据插入效率低下的解决方法

#include <iostream> #include <winsock2.h> #include <string> #include "mysql.h" #pragma comment(lib, "libmysql.lib"); using namespace std; int main() { MYSQL mysql; mysql_init(&mysql); // 初始化 MYSQL *ConnStatus = my