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的更多相关文章

  1. Ignite 配置更新Oracle JDBC Drive

           如果使用Oracle 12C 作为Ignite 的Repository的话,在Repository Createion Wizard的配置过程中,会出现ORA-28040:No matc ...

  2. 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 ...

  3. 高性能 Oracle JDBC 编程

    了解如何利用连接和语句池特性来提高 Oracle 驱动的 JDBC 程序的性能.作者:Yuli Vasiliev2009 年 4 月发布使用诸如连接池和语句池等池技术可以显著提高数据库密集型应用程序的 ...

  4. java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver 错误的解决办法

    java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver 错误的解决办法 (2011-05-05 16:08:05) 转载▼ ...

  5. mysql和oracle jdbc连接

    加载驱动. Class.forName("oracle.jdbc.driver.OracleDriver"); 1 创建连接. Connection con = DriverMan ...

  6. Eclipse中启用Oracle jdbc logging

    根据自己用的JRE版本, jre1.5选择ojdbc5_g.jar, jre6选择ojdbc6_g.jar, 只有带_g的dirver才输出debug信息. maven 的配置信息: <depe ...

  7. 在MAVEN仓库中添加ORACLE JDBC驱动

    本文转载自 http://www.cnblogs.com/leiOOlei/archive/2013/10/21/3380568.html 因为已经是第二次遇到,所以COPY过来,怕以后别人的BLOG ...

  8. 连接oracle jdbc

    我使用的是精简版的oracle. 1  导入oracle驱动包 oracle下路径 D:\oracle\app\oracle\product\11.2.0\server\jdbc\lib\ojdbc6 ...

  9. maven oracle jdbc jar

    1.problem describe: when your dependency jar about oracle use code like this: <!-- oracle-connect ...

随机推荐

  1. Unable to establish SSL connection

    当wget出现如下错误: Can't connect to HTTPS URL because the SSL module is not available 需要安装: # sudo apt-get ...

  2. App的开发过程(转载)

    来源:https://www.cnblogs.com/sanwenyu/p/7234616.html 不同的项目管理模式或许会有完全不同的流程步骤.但是专业性几乎是保证产品质量的唯一准则. App的开 ...

  3. rest framework 之序列化

    一.示例 restful work 的序列号就类似于 Django 的 Form 表单. 1.api/urls.py from django.urls import path, re_path fro ...

  4. linux cgroups简介(上)

    Linux CGroups简介 1.CGroups是什么 与Linux namespace对比来看,Linux namespace用来限制进程的运行范围或者运行环境的可见性,比如:uts限制进程读取到 ...

  5. win10和linux引导问题(没有系统选择界面)

    由于最近学习嵌入式和c模块化编程,需要使用Linux系统,但是编程之外,WIN10还是主力系统,决定装双系统. 往常一样,百度装双系统方法,网上千篇一律,大都一个套路. 首先,WIN10 下,新开一个 ...

  6. BFS (1)算法模板 看是否需要分层 (2)拓扑排序——检测编译时的循环依赖 制定有依赖关系的任务的执行顺序 djkstra无非是将bfs模板中的deque修改为heapq

    BFS模板,记住这5个: (1)针对树的BFS 1.1 无需分层遍历 from collections import deque def levelOrderTree(root): if not ro ...

  7. 201671030102陈飞 实验十四 团队项目评审&课程学习总结

    项目 内容 这个作业属于哪个课程 2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十四 团队项目评审&课程学习总结 课程学习目标 1.掌握软件项目评审会议流程 ...

  8. 用 gradle 运行 spring boot 项目

    用 gradle 运行 spring boot 项目(网页中的第6章:https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/gradle-plug ...

  9. Properties 取值和设置函数 Hashtable的静态内部类Entry的结构和克隆方法

  10. 利用python画小猪佩奇

    import turtle as t t.pensize(4) t.hideturtle() t.colormode(255) t.color((255,155,192),"pink&quo ...