文档章节

Oracle JDBC驱动内存

O
 Only_小白
发布于 2017/09/08 09:15
字数 2014
阅读 3
收藏 0
点赞 0
评论 0

一、JDBC驱动内存机制

       Oracle为了提高数据库访问性能,提供了服务器端缓存和客户端缓存这两种缓存。其中,Oracle客户端缓存可能会使用大量的内存,这是一种有意识的设计选择,在使用大量内存与提高性能之间做出权衡,用内存换取性能。

     其中主要对内存产生较大影响的缓存有以下几种:

     1.查询结果缓存

     JDBC驱动缓存中缓存的是sql的执行结果,这样相同sql再次执行时可以直接从缓存中获取数据,而不需要与服务器端交互,从而达到提高查询性能的作用。默认情况下,我们在使用一个数据库连接去执行查询时,JDBC驱动会为连接内的每一个Statement(Statement、PreparedStatement、CallableStatement)创建两个buffer:byte[]和char[]。其中char[]用来保存所有字符类型的行数据,如:CHAR,VARCHAR2,NCHAR等,byte[]用来保存所有的其它类型的行数据。这些buffer在在SQL被解析的时候分配,一般也就是在第一次执行该Statement的时候。Statement会持有这两个buffer,直到它被关闭。

     2.PreparedStatement缓存

     大型系统中往往很多次执行相同的sql,出于性能方面考虑,驱动重用了PreparedStatement,而不是每次为每条sql创建新的PreparedStatement。JDBC驱动内置了一个语句缓存-- Implicit Statement Cache(它的大小默认为0,即不缓存PreparedStatement)。这个语句缓存对用户是透明的,可通过配置连接属性,设置缓存的PreparedStatement数量。

     3.buffer缓存

     Oracle11.2版本驱动中,驱动程序中提供了一个内存管理更复杂的方法。这个方法有两个目标,最大限度减少内存未使用量和最小化buffer分配带来的成本。驱动程序在每个连接内部创建了一个buffer缓存(buffer cache)。当一个PreparedStatment使用结束被放回Implicit Statement Cache中时,它的buffer会被缓存到buffer缓存中buffer桶(buncket)中,一个buffer桶中的所有buffer都是相同大小且这个大小是预先确定的。当一个PreparedStatement是从Implicit Statement中取出时,也同时会从buffer缓存中根据查询结果的大小从适当的buffer桶中取出buffer。

驱动提供一个连接属性oracle.jdbc.maxCachedBufferSize。它是一个int字符串,默认是Integer.MAX_VALUE。此属性限定了保存在buffer桶中buffer最大的长度大小。超过这个大小 的buffer会在PreparedStatement被放回Implicit Statement Cache中时释放,小于这个大小的buffer会被缓存到相应的buffer桶中,当PreparedStatement从Implicit Statement Cache中取出时,小于maxCachedBufferSize的buffer会从合适的buffer 桶中取出,大于maxCachedBufferSize的buffer 会被重新创建。

    

二、内存占用情况

       buffer是在SQL解析的时候被分配的,buffer的大小并不取决于查询返回的行数据的实际长度,而是行数据可能的最大的长度。在SQL解析时,每列的类型是已知的,从该信息中驱动程序可以计算存储每一列所需的内存的最大长度。驱动程序也有fetchSize属性,也就是每次fetch返回的行数。有了每列有大小和行数的大小,驱动程序可以由此计算出一次fetch所返回的数据最大绝对长度。这也就是所分配的buffer的大小。

     字符数据存储在char[]buffer中。Java中的每个字符占用两个字节。一个VARCHAR2(10)列将包含最多10个字符,也就是10个Java的字符,也就是每行20个字节。一个VARCHAR2(4000)列将占用每行8K字节。重要的其实是column的定义大小,而不是实际数据的大小。一个VARCHAR2(4000)但是只包含了NULL的列,仍然需要每行8K字节。buffer是在驱动程序看到的查询结果之前被分配的,因此驱动程序必须分配足够的内存,以应付最大可能的行大小。一个定义为VARCHAR2(4000)的列最多可包含4000个字符。Buffer必须大到足以容纳4000个字符分配,尽管实际的结果数据可能没有那么大。

     BFILE,BLOB和CLOB会被存储为locator。Locator可高达4K字节,每个BFILE,BLOB和CLOB列的byte[]必须有至少每行4K字节。RAW列最多可以包含4K字节。其它类型的则需要很少的字节。一个合理的近似值是假设所有其它类型的列,每行占用22个字节。

      假设目前数据库中,每条记录定义:10K,fetchsize:50,PreparedStatementCache:100,连接池max值:30, 连接池个数:2个。在极端情况下,内存占用会达到:2*10K*50*100*30*2=6GB 。

三、控制参数说明

       说明以下参数都可以通过-D方式添加到启动sofa容器的启动参数中设置系统属性。

 

     1.oracle.jdbc.maxCachedBufferSize

此属性限定了保存在buffer缓存中buffer的最大的长度大小。它是一个int字符串,默认是Integer.MAX_VALUE。超过这个大小 的buffer会在PreparedStatement被放回Implicit Statement Cache中时释放,小于这个大小的buffer会被缓存到相应的buffer桶中,当PreparedStatement从Implicit Statement Cache中取出时,小于maxCachedBufferSize的buffer会从合适的buffer 桶中取出,大于maxCachedBufferSize的buffer 会被重新创建。

     2. oracle.jdbc.useThreadLocalBufferCache

默认值:false,默认情况下,buffer缓存中存储在连接中的,即每个连接都会有自己的缓存。如果在真实业务场景中,我们存在大量这样的使用场景:在一个处理逻辑中,我们需要使用多个连接去访问数据库,那么这些连接各自都有自己的缓存。且相对于线程数来说存在大量空闲数据库连接,由于默认情况下buffer缓存是附属于每个连接的,空闲连接的结果就是buffer缓存中有很多不会被用到的buffer,会用很多没必要的内存。我们可以把oracle.jdbc.useThreadLocalBufferCache属性设置为true,这样我们可以让业务处理逻辑所在线程内的所有连接共用一个缓存,即把buffer存储到线程中,如此一来,线程内使用到的连接都会共用当前线程内的buffer。该属性可以通过-D设置System property或者通过的调用getConnection时的connection property。

    3. OracleStatement.setLobPrefetchSize

              LOB字段默认大小为4000bytes。设置BLOB字段每次获取字节数据的大小,这种方式也可以限制一行查询结果的大小。因sofa底层使用的是hibernate,不支持对该参数的设置控制。在使用jdbc方式时可以设置该参数。

     4.fetchSize

              buffer的大小不是由查询的实际行数决定的,而是由每次获取的行数决定的。这个每次获取的行数也就是fetchSize,见下图。

      

JDBC驱动默认是10。我们可以在hibernate_properties_config.xml中通过配置

   <prop key="hibernate.jdbc.fetch_size">50</prop>来设置。

       或在连接池中按不同连接池的属性去配置fetchSize大小。

5.优化连接池

        buffer默认是存储在每个数据库连接中的。连接池中配置太多的连接,会导致连接大部分空闲。在极端情况下,如果连接池内的连接被全部使用,每个连接内都会有查询结果缓存,就会导致应用程序内存占用暴增。

© 著作权归作者所有

共有 人打赏支持
O
粉丝 2
博文 22
码字总数 11544
作品 0
昌平
Hive在windows端的图形化连接工具

Hive官网上介绍过几种windows端的连接方式,本文主要介绍如何使用Oracle SQL Developer连接hive。 1.下载并解压Oracle SQL Developer 从 http://www.oracle.com/technetwork/developer-tool...

Matthew.L ⋅ 05/29 ⋅ 0

升级到JDK9的一个BUG,你了解吗

概述 前几天在一个群里看到一个朋友发了一个demo,说是JDK的bug,昨天在JVM的一个群里又有朋友发了,觉得挺有意思,分享给大家,希望大家升级JDK的版本的时候注意下是否存在这样的代码,如果...

你假笨 ⋅ 06/06 ⋅ 0

002. 深入JVM学习—JVM对象访问模式

Object obj = new Object(); 分析 --- Object obj:描述的是保存在栈内存之中,而后保存有堆内存的引用,这个数据会保存在本地变量表中(变量表描述有哪些对象,保存对象栈的位置,栈对应着堆...

影狼 ⋅ 昨天 ⋅ 0

java编程学习常见面试题及答案

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互...

Java小辰 ⋅ 05/22 ⋅ 0

【小马哥】Spring Cloud系列讲座

这里为大家推荐一个不错的Spring Cloud系列讲座,讲师介绍如下: 小马哥,阿里巴巴技术专家,从事十余年Java EE 开发,国内微服务技术讲师。目前主要负责微服务技术推广、架构设计、基础设施...

杜琪 ⋅ 03/02 ⋅ 0

Oracle Java SE 8 发行版更新:限制商业或生产用途

Oracle Java SE 8 发行版更新 Oracle Java SE 8 的公开更新仍面向单独的个人使用提供,至少持续至 2020 年底。 2019 年 1 月以后发布的 Oracle Java SE 8 公开更新将不向没有商用许可证的业务...

抢小孩糖吃 ⋅ 04/18 ⋅ 39

Confluence 6 新 Confluence 安装配置一个数据源连接

如果在你的 Tomcat 中配置了数据源,并且Confluence 设置指南在安装的时候检测到这个配置的时候,配置数据源的选项将会提供给你进行配置。入股你希望使用数据源,请参考下面的配置。 1. 停止...

honeymose ⋅ 06/08 ⋅ 0

Java常见的面试问题(带答案),自己答出来多少?

前言:觉得对自己有帮助别忘了也给其他小伙伴一起分享哦! 问题:如果main方法被声明为private会怎样? 答案:能正常编译,但运行的时候会提示”main方法不是public的”。 2.问题:Java里的传...

迷你芊宝宝 ⋅ 昨天 ⋅ 0

Java虚拟机标准(第10版)第一章(节选)翻译与评注

英文原文链接:https://docs.oracle.com/javase/specs/jvms/se10/html/jvms-1.html 评注是括在鱼尾号之间的文字,其余均为翻译 Java虚拟机是Java平台的基石,这种技术实现了诸如跨平台、生成...

Jelif ⋅ 06/03 ⋅ 0

Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!

前几天写了一篇 Java 8 即将在 2019 年停止免费向企业提供更新的文章,企图迫使用户向更新一代的 Java 版本升级,但让人遗憾的是,小编今天收到了 Oracle Java 版本的升级推送,装完居然是 ...

Java技术栈 ⋅ 04/27 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Sqoop

1.Sqoop: 《=》 SQL to Hadoop 背景 1)场景:数据在RDBMS中,我们如何使用Hive或者Hadoop来进行数据分析呢? 1) RDBMS ==> Hadoop(广义) 2) Hadoop ==> RDBMS 2)原来可以通过MapReduce I...

GordonNemo ⋅ 25分钟前 ⋅ 0

全量构建和增量构建的区别

1.全量构建每次更新时都需要更新整个数据集,增量构建只对需要更新的时间范围进行更新,所以计算量会较小。 2.全量构建查询时不需要合并不同Segment,增量构建查询时需要合并不同Segment的结...

无精疯 ⋅ 35分钟前 ⋅ 0

如何将S/4HANA系统存储的图片文件用Java程序保存到本地

我在S/4HANA的事务码MM02里为Material维护图片文件作为附件: 通过如下简单的ABAP代码即可将图片文件的二进制内容读取出来: REPORT zgos_api.DATA ls_appl_object TYPE gos_s_obj.DA...

JerryWang_SAP ⋅ 53分钟前 ⋅ 0

云计算的选择悖论如何对待?

导读 人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云...

问题终结者 ⋅ 今天 ⋅ 0

637. Average of Levels in Binary Tree - LeetCode

Question 637. Average of Levels in Binary Tree Solution 思路:定义一个map,层数作为key,value保存每层的元素个数和所有元素的和,遍历这个树,把map里面填值,遍历结束后,再遍历这个map,把每...

yysue ⋅ 今天 ⋅ 0

IDEA配置和使用

版本控制 svn IDEA版本控制工具不能使用 VCS-->Enable Version Control Integration File-->Settings-->Plugins 搜索Subversion,勾选SVN和Git插件 删除.idea文件夹重新生成项目 安装SVN客户......

bithup ⋅ 今天 ⋅ 0

PE格式第三讲扩展,VA,RVA,FA的概念

作者:IBinary 出处:http://www.cnblogs.com/iBinary/ 版权所有,欢迎保留原文链接进行转载:) 一丶VA概念 VA (virtual Address) 虚拟地址的意思 ,比如随便打开一个PE,找下它的虚拟地址 这边...

simpower ⋅ 今天 ⋅ 0

180623-SpringBoot之logback配置文件

SpringBoot配置logback 项目的日志配置属于比较常见的case了,之前接触和使用的都是Spring结合xml的方式,引入几个依赖,然后写个 logback.xml 配置文件即可,那么在SpringBoot中可以怎么做?...

小灰灰Blog ⋅ 今天 ⋅ 0

冒泡排序

原理:比较两个相邻的元素,将值大的元素交换至右端。 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第...

人觉非常君 ⋅ 今天 ⋅ 0

Vagrant setup

安装软件 brew cask install virtualboxbrew cask install vagrant 创建project mkdir -p mst/vmcd mst/vmvagrant init hashicorp/precise64vagrant up hashicorp/precise64是一个box......

遥借东风 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部