Oracle JDBC prefetch: how to avoid running out of RAM
Using Oracle java JDBC (ojdbc6 11.2.0.4), loading a query with many rows takes forever (high latency environment. This is apparently the default prefetch in Oracle JDBC is default size "10" which requires a round trip time once per 10 rows. I am attempting to set an aggressive prefetch size to avoid this.
PreparedStatement stmt = conn.prepareStatement("select * from tablename");
statement.setFetchSize(10000);
ResultSet rs = statement.executeQuery();
This can work, but instead I get an out of memory exception. I had presumed that setFetchSize would tell it to buffer "that many rows" as they come in, using as much RAM as each row requires. If I run with 50 threads, even with 16G of -XMX space, it runs out of memory. Feels almost like a leak:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.lang.reflect.Array.newArray(Native Method)
at java.lang.reflect.Array.newInstance(Array.java:70)
at oracle.jdbc.driver.BufferCache.get(BufferCache.java:226)
at oracle.jdbc.driver.PhysicalConnection.getCharBuffer(PhysicalConnection.java:7422)
at oracle.jdbc.driver.OracleStatement.prepareAccessors(OracleStatement.java:983)
at oracle.jdbc.driver.T4CTTIdcb.receiveCommon(T4CTTIdcb.java:273)
at oracle.jdbc.driver.T4CTTIdcb.receive(T4CTTIdcb.java:144)
at oracle.jdbc.driver.T4C8Oall.readDCB(T4C8Oall.java:771)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:346)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:861)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1145)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1267)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3493)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1491)
....
What can I do to still get prefetch but not run out of RAM? What is going on?
The closest related item on SO is this: http://stackoverflow.com/a/14317881/32453
Basically, oracle's default strategy for later ojdbc jars is to "pre allocate" an array per "prefetch" row that accomodates for the largest size conceivably possible to return from that query. So in my case I had some VARCHAR2(4000) in there, so 50 threads * 3 columns of varchar2's * 4000 was adding up to more than gigabytes of RAM [yikes]. There does not appear to be an option to say "don't pre allocate that array, just use the size needed." Ojdbc even keeps these preallocated buffers around between preparedstatements so it can reuse them. Definitely a memory hog.
The fix was to determine the maximum actual column size, then replace the query with (assuming 50 is the max size) select substr(column_name, 0, 50)
as well as profile and only use as high of setFetchSize as actually made significant speed
ments.
Other things you can do: decrease the number of prefetch rows, increase Xmx parameter, only select the columns you need.
Once we were able to use at least prefetch 400 [make sure to profile to see what numbers are good for you, with high latency we saw
ments up to prefetch size 3-4K] on all queries, performance
d dramatically.
I suppose if you wanted to be really aggressive against sparse "really long" rows you might be able to re-query when you run into these [rare] rows.
Details ad nauseum here
最新还有个解决方法,使用ojdbc8,已经是按需分配模式。
Oracle JDBC prefetch: how to avoid running out of RAM的更多相关文章
- Ignite 配置更新Oracle JDBC Drive
如果使用Oracle 12C 作为Ignite 的Repository的话,在Repository Createion Wizard的配置过程中,会出现ORA-28040:No matc ...
- created a ThreadLocal with key of type [oracle.jdbc.driver.AutoKeyInfo$1]
环境: spring4.3, mybatis3.5.2, ojdbc8_8c(oracle 18c jdbc) 调试状态下退出时,提示: 严重 [main] org.apache.catalina.l ...
- 高性能 Oracle JDBC 编程
了解如何利用连接和语句池特性来提高 Oracle 驱动的 JDBC 程序的性能.作者:Yuli Vasiliev2009 年 4 月发布使用诸如连接池和语句池等池技术可以显著提高数据库密集型应用程序的 ...
- java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver 错误的解决办法
java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver 错误的解决办法 (2011-05-05 16:08:05) 转载▼ ...
- mysql和oracle jdbc连接
加载驱动. Class.forName("oracle.jdbc.driver.OracleDriver"); 1 创建连接. Connection con = DriverMan ...
- Eclipse中启用Oracle jdbc logging
根据自己用的JRE版本, jre1.5选择ojdbc5_g.jar, jre6选择ojdbc6_g.jar, 只有带_g的dirver才输出debug信息. maven 的配置信息: <depe ...
- 在MAVEN仓库中添加ORACLE JDBC驱动
本文转载自 http://www.cnblogs.com/leiOOlei/archive/2013/10/21/3380568.html 因为已经是第二次遇到,所以COPY过来,怕以后别人的BLOG ...
- 连接oracle jdbc
我使用的是精简版的oracle. 1 导入oracle驱动包 oracle下路径 D:\oracle\app\oracle\product\11.2.0\server\jdbc\lib\ojdbc6 ...
- maven oracle jdbc jar
1.problem describe: when your dependency jar about oracle use code like this: <!-- oracle-connect ...
随机推荐
- Android-----CheckBox复选使用(实现简单选餐)
直接上代码: xml布局: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmln ...
- 史上最全的整合第三方登录的工具JustAuth
JustAuth,如你所见,它仅仅是一个第三方授权登录的工具类库,它可以让我们脱离繁琐的第三方登录SDK,让登录变得So easy! 参考图例 授权gitee 授权github 授权weibo 授权钉 ...
- Kombu源码分析(一)概述
Celery是Python中最流行的异步消息队列框架,支持RabbitMQ.Redis.ZoopKeeper等作为Broker,而对这些消息队列的抽象,都是通过Kombu实现的.Kombu实现了对AM ...
- spark遇到的问题及解决方法
1. 表中数据过亿,加载速度过慢,而我只需要加载增量数据 如:加载昨天一整天的数据,添加predicates分区,方法如下: //predicates相当于是把昨天的数据分成一个区,其它的数据不加载 ...
- Jmeter中Switch Controller逻辑控制器用法
当Switch Controller中Switch Value设置为0时,执行第0+1个子节点:Switch Value设置为1时,执行第1+1个子节点:Switch Value设置为2时,执行第2+ ...
- Reset.css和Normalize.css样式表初始化相关
(1)Reset.css 简介:在HTML标签在浏览器里有默认的样式,例如 p 标签有上下边距,strong标签有字体加粗样式,em标签有字体倾斜样式.不同浏览器的默认样式之间也会有差别,例如ul默认 ...
- Shell脚本监控Linux某个后台进程,当进程死掉后重新启动服务,以httpd为例
Shell脚本如下: vim monitor.sh #!/bin/bash while true # 无限循环 flag=`ps -aux |grep "httpd" |grep ...
- Invalid mime type "application nd.ms-excel; charset=utf-8;charset=utf-8": does not contain '/'
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is ...
- jenkins邮件配置以及邮件添加附件详解
1.在系统管理-系统设置 中找到邮件配置模块 填写情况如下图 第一步,填写系统管理员邮箱 第二步,填写邮箱配置 第三步,然后在项目中添加邮箱配置 项目中邮件设置中关于附件添加 因为我的项目目录中分3 ...
- 文件夹备份tar脚本
#! /bin/sh SOURCEDIR=/data/OA DESTDIR=/data/OAbackup TARDIR=/data/gz #拷贝源文件夹至目标文件夹 cp -r $SOURCEDIR ...