JDBC处理大结果集

一.背景说明

之前在处理一个优化task时接触到了Jdbc对于大结果集的处理相关内容,记录下。问题开始于前置机抽数程序在抽取大数据量数据时出现卡死的情况。数据源方面客户使用的是Oracle数据库,使用Jdbc直接连接数据库。根据字段数量及类型不同,大概在单个接口数据量达到10万~15万左右就会出现卡死。

二.原因探寻

猜测一:
一开始以为是因为写入的csv文件对大小及记录数有限制,因为每次大概都是写到70多M的时候就会卡死,而且比如xls文件的根据office版本不同确实是有限制的。但经过网上搜索及实际验证后发现,并不是因为这个原因。不过这个地方还是可以找到可以优化的点,就是按大小或记录数分批写文件,当行数真的有要求时可以类似于这样做:
while ( rs.next() ) /* 此处处理业务逻辑 */
{
count++;
if ( count % pageSize == 0 )
{
System.out.println( " 写入到第 " + (count/pageSize) + " 个文件中!" );

}

}

猜测二:
这个时候又在想应该一次性处理的结果集太大导致无法处理,哪我们能不能试试把结果集分割下,或者使一次处理的结果集尽量小点呢?由此,研究了下分页查询的用法,Oracle里暂时还不能用limit,所以是借助伪列rownum来实现的,如下:
"select * from (select rownum as rowno,ai.* " +
"from ai, " +
" mv, " +
"hscf.hscf_approved_ou_vendors haov, "+
"hscf.hscf_apr_ou_vdr_sync_timestamp haov_ts "+
"where ai.view_id = mv.mv_id " +
" " +
"and ai.org_id = haov.operating_unit_id " +
"and mv.vendor_id = haov.vendor_id " +
"and ? = haov.interface_entity_code " +
"and ‘Y‘ = haov.enabled_flag " +
"and haov.interface_entity_code = haov_ts.interface_entity_code " +
"and haov.operating_unit_id = haov_ts.operating_unit_id " +
"and haov.vendor_id = haov_ts.vendor_id "+
"and rownum <= * ) " +
"where rowno > ( -1) * " ;

但是这个用上之后,发现其实并不能解决问题。甚至就总的效率而言,反而是下降了。因为每次找到分页的起始点其实也是会花费时间的,页数越往后时间花的越多。由此可以记录一下:分页并不适用于提高总的效率。只是有些时候我们不需要获取所有记录,只是想查看一部分的时候,比如前端的页面展示。实际上,因为我们这里为了提高查询效率使用了物化视图,该建的索引都建了,去掉了不必要的Order by,还使用了PARALLEL特性。所以到这里可以发现问题的关键并不在于磁盘IO,SQL效率上,应该从别的角度去考虑。

猜测三:
上面的方法虽然并没有实际解决问题,但其实还是提供了一些有用的想法,且让我有所收获的。到这里其实我们应该冷静下来,好好去理一下思路,可以知道重点其实应该在结果集上,所以我们应该好好的研究下ResultSet这个类的各个属性方法。
由此,我获得了一些有用的信息,并最终结局了问题。Jdbc只是接口规范,实际的实现还在于驱动类,说这句话的目的在于提醒,解决这种问题一定要具体到数据库类型。比如,网上说使用setFetchSize修改每次提取的记录数可以解决Jdbc大数据量抽取效率的问题,但我看了下人家用的是Mysql。而在我的这个案例里,数据库用的Oracle,每次默认的fetchSize为10,而这个其实是有Oracle给出的一个比较合理的大小。因为,一次发送的太多,每次花费在网络传输上的时间也会变多。经过反复查找,终于发现问题的关键在于这里:
//modified by zhuqingxin at 2018-09-05 for large data extract
//pst = getConnection().prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
pst = getConnection().prepareStatement( sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY );
//modified by zhuqingxin at 2018-09-05 for large data extract
原来的那种结果集设置不合理,导致JVM会把结果集主要存储于内存中,而系统分配给JVM的内存应该是有限制的。当数据量很大的时候,自然就会出问题。后面那种设置按我理解,应该就是主要把结果集存储于磁盘,到需要的时候再取了。这个优化修改,总共200多M的数据文件大概15分钟全部处理完成并发送到服务器。所以,我之前做的那些分批写文件,后台分页查询,把文件改成文件列表之类的其实都没什么用。解决问题的关键其实就一句话。

三.参考

https://www.cnblogs.com/jay763190097/p/6813792.html
https://www.cnblogs.com/anee/archive/2011/12/20/2675796.html
https://blog.csdn.net/IT_xiaocao/article/details/64920381?locationNum=2&fps=1
https://blog.csdn.net/seven_3306/article/details/9303979
https://blog.csdn.net/seven_3306/article/details/9303879
https://www.cnblogs.com/bukudekong/archive/2011/06/22/2086528.html
https://blog.csdn.net/ooad/article/details/3317705
https://wenku.baidu.com/view/72207982fab069dc502201c3.html
https://www.cnblogs.com/zhangzhxb/p/6336484.htm

原文地址:https://www.cnblogs.com/zhuqingxin/p/9866704.html

时间: 2024-11-08 09:30:58

JDBC处理大结果集的相关文章

正确使用MySQL JDBC setFetchSize()方法解决JDBC处理大结果集 java.lang.OutOfMemoryError: Java heap space

昨天在项目中需要对日志的查询结果进行导出功能. 日志导出功能的实现是这样的,输入查询条件,然后对查询结果进行导出.由于日志数据量比较大.多的时候,有上亿条记录. 之前的解决方案都是多次查询,然后使用limit 限制每次查询的条数.然后导出.这样的结果是效率比较低效. 那么能不能一次查询就把所有结果倒出来了?于是我就使用一次查询,不使用limit分页.结果出现 java.lang.OutOfMemoryError: Java heap space问题. 看来是DB服务器端将一次将查询到的结果集全部

jdbc mysql crud dao模型 sql注入漏洞 jdbc 操作大文件

day17总结 今日内容 l JDBC 1.1 上次课内容总结 SQL语句: 1.外键约束:foreign key * 维护多个表关系! * 用来保证数据完整性! 2.三种关系: * 一对多: * 一个客户可以对应多个订单,一个订单只属于一个客户! * 建表原则: * 在多的一方创建一个字段,作为外键指向一的一方的主键!!! * 多对多: * 一个学生可以选择多个课程,一个课程也可以被多个学生选择! * 建表原则: * 创建第三张表,第三张表中放入两个字段,作为外键分别指向多对多双方的主键! *

JDBC学习笔记:用JDBC处理大段数据

1.数据库——创建数据表 1 create table clob_test 2 ( 3 id integer not null auto_increment primary key, 4 big_text text not null 5 ); 2.用JDBC处理大段文本数据 (1)将文本数据写入数据库 1 @Test 2 public void create() throws SQLException, IOException { 3 Connection conn = null; 4 Prep

[题解+总结]动态规划大合集II

1.前言 大合集总共14道题,出自江哥之手(这就没什么好戏了),做得让人花枝乱颤.虽说大部分是NOIP难度,也有简单的几道题目,但是还是做的很辛苦,有几道题几乎没思路,下面一道道边看边分析一下. 2.lis 最长上升子序列 唯一一道裸题,但是O(n^2)过不了,临时看了看O(n log n)的二分做法和线段树做法.先来讲讲简单的二分做法,其本质就是在O(n^2)上进行优化,需要证明一个结论.设当前处理数列第k位,存在: (1)a[i]<a[j]<a[k]: (2)i<j<k: (3

[知识点]NOIP动态规划大合集

1.前言 NOIP2003-2014动态规划题目大合集,有简单的也有难的(对于我这种动态规划盲当然存在难的),今天就把这些东西归纳一下,做一个比较全面的总结,方便对动态规划有一个更深的理解. 2.NOIP2003 加分二叉树 树形DP入门题,根据题意,一个树的加分=左子树*右子树+根节点,由此可以设f[i][j]为子树i到j的加分,则有方程:f[i][j]=max{d[t]+f[i,t-1]*f[t+1,j]} ( t∈[i,j] ) 3.NOIP2004 合唱队形 应该是最简单的一道了,枚举队

JDBC之 大数据内容的传输

JDBC之 大数据内容的传输 什么是大数据内容? 在数据库中,有一条一条的记录,记录中很多字段都是几个字符就够的,假如现在要把一部小说存入数据库,这本小说当然不是几个字符组成,而是由几万字组成,这本小说的数据我们就可以说是大数据,生活中当然有各种各样的大数据:电影,音乐,图片等等... 大字符数据内容操作 大字符内容:通常是指很长的字符类型的文件,例如小说,故事等等,内容有字符组成. 下面说明一下MySQL与Oracle中的大数据类型 数据种类 数据大小 MySQL Oracle 字符 小 ch

从零开始学数据分析,什么程度可以找到工作?( 内附20G、5000分钟数据分析工具教程大合集 )

从零开始学数据分析,什么程度可以找到工作?( 内附20G.5000分钟数据分析工具教程大合集 ) 我现在在Coursera上面学data science 中的R programming,过去很少接触过统计.计算机这两个学科,现在很想转行做数据.问题如下: 1.Data需要学到什么程度可以找工作?2.初级的数据分析会做哪些工作?3.数据分析有什么小方向吗?4.想要深度做数据分析有怎样的建议? 5.统计的学习应该从哪里下手? 本文将给你以上问题所有答案,文末还有UniCareer为大家独家整理的20

Lucene搜索方式大合集

package junit; import java.io.File; import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import org.apache.lucene.document.Document; import or

Android 软件开发与游戏开发1 至 32系列博文大合集

Android 软件开发与游戏开发1 至 32系列博文大合集Android 软件开发与游戏开发1 至 32系列博文大合集 http://www.qdmm.com/BookReader/17958,65822595.aspxhttp://www.qdmm.com/BookReader/17958,65822597.aspxhttp://www.qdmm.com/BookReader/17958,65822598.aspxhttp://www.qdmm.com/BookReader/17958,65