JDBC内存管理—varchar2(4000)的影响

        今天在项目评审中遇到到一个问题,一个表的字段如comment,开发想用varchar2(4000),而我建议在满足应用场景的情况下,尽量减少长度,当时就抛出了一个问题,varchar2(4000)和varchar2(40)那个好,当时我也只是简单的回答了一下,说道varchar2(xx)的字段会在内存中分配空间大小为字段定义的长度。  回来后有想了想,自己也没有弄清楚其中的原来,于是问了问同事,查了查资料,说法都有理,如索引长度的限制 ,可以作为数据库层面的约束啊等等.最后还是翻了Oracle JDBC内存管理文档一读,终于明白了其中的原理。                        

        在10g中,oracle jdbc driver能够使用较大的内存,为了提高jdbc的性能,最重大的改变是在内存的使用上(内存换时间)。

        内存中主要用于存放查询结果,每个statement(如java中的prepared statement,callable statement)包括了两个buffers,一个为byte buffer,另一个为 char buffer。Char buffer用于存放所有字符类型的行,比如:char,varchar2,nchar等,byte buffer用于存储其他的数据类型的行。这些buffer在sql解析的时候分配,直到statement关闭(colse)的时候释放。

        Buffer的大小并不取决于查询返回的行的大小,当sql被解析后,driver根据每列的数据类型计算出最大的内存容量来存储每一列。

        同时,driver有一个fetchsize(指定每次使用Array Fetch 法检索出的数据行数。

    最佳数目取决于系统的性能:

   •如果数目太低,系统会多次检索少量数据,因而影响性能。

   •如果数目太高,系统执行检索操作的次数会降低,但每次需要更多的内存)

    那么在一次fetch时,driver就能根据每列长度和检索的行数计算出buffer的大小。

       Character data存储在char buffer之中,varchar2(10)的列将容纳最大长度的10字节,如果是定义为varchar2(4000)的列,则每行将占4000字节,不管实际中列存储了多少数据。在Driver知道查询结果之前,必须分配足够的内存用于存储可能最大的结果。

       Bfile,blob,raw和clob数据存储在byte buffer之中,这些数据类型能够达到4kbytes,需要每行至少4000bytes;其他的一些数据类型date,number每行大约为22bytes(估计值)。

         例子:CREATE TABLE TAB (ID NUMBER(10), NAME VARCHAR2(40), DOB DATE)

ResultSet r = stmt.executeQuery(“SELECT * FROM TAB”);

        当driver执行查询方法的的时候,数据库将解析sql,得到三列的信息:一列number(10),一列varchar2(40),一列date,第一列每行需要22字节,第二列每行需要40字节,第三列需要每行需要22字节,因此一行需要84字节,fetch size 为10行,那么dirver将会分配 char buffer:10*40=400 bytes;byte buffer将会分配:10*(22+22)=440bytes,总共840bytes。

           那么在定义varchar(4000)和定义varchar(20)的区别是很大的,varchar(4000)每行需要4000字节,而varchar(20)需要20字节,因此会造成内存空间的浪费。

         在明白了varchar字段在jdbc中分配内存的原理,设计表结构的时候,尽量避免使用varchar(large number),这样会给应用服务器节省一些内存,如果在大量连接访问的时候,RAM=connections*fetch的节省也是不可小视的。其实也可以想象一下,现实场景中,有那个用户会给你写到几千字的评论,又有谁查看你几千字的评论,那么在应用页面端就可以限制输入到db中的容量。

        可见在一些细小的问题上,也能制造出一些麻烦出来。注重细节,不可忽视。

时间: 2024-08-11 17:45:42

JDBC内存管理—varchar2(4000)的影响的相关文章

内存管理内幕

动态分配的选择.折衷和实现 Jonathan Bartlett (johnnyb@eskimo.com), 技术总监, New Media Worx 本文将对 Linux 程序员可以使用的内存管理技术进行概述,虽然关注的重点是 C 语言,但同样也适用于其他语言.文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存. 好文章收藏! 原文地址:http://www.ibm.com/developerwork

可能影响容器化应用程序的cgroup内存管理问题

近日,LinkedIn工程团队发表了一篇题为"不要让Linux控制组不受控制地运行"的文章.控制组(cgroup)是Linux的一项特性,像Docker和CoreOS这样的项目使用该特性限制进程的资源使用.该文概括地介绍了cgroup在内存管理方面存在的几个可能导致性能退化的问题以及可能的解决方案. Cgroup是一种可以确保应用程序使用的资源不超出限额的机制,但不保证隔离性.一个操作系统实例中可以运行多个cgroup,其中每一个所使用的内存.CPU等都有不同的限额.不过,当有额外的内

内存管理 之 存储器硬件知识

接下来,为了顺应Linux Kernel的学习,在操作系统方面首先学习的是内存管理.首先主要讲解物理内存的相关知识.本节主要讲解存储器的基础硬件知识,下一节讲解存储器的层次结构.   存储器是计算机系统的重要组成部分,它在计算机系统中的作用是存放程序和数据.存储器不仅使计算机具有记忆功能,而且是计算机高速自动运行的基础. 作为计算机的核心部件之一,存储器直接关系到整个计算机系统性能的高低.如何以合理的成本搭建出容量和速度都满足要求的存储器系统,始终是计算机体系结构设计中的关键问题之一:一方面,人

iOS ARC 内存管理要点

前言 在讨论 ARC 之前,我们需要知道 Objective-C 采用的是引用计数式的内存管理方式,这一方式的特点是: 自己生成的对象自己持有.比如:NSObject * __strong object = [NSObject alloc] init];. 非自己生成的对象自己也能持有.比如:NSMutableArray * __strong array = [NSMutableArray array];. 自己持有的对象不再需要时释放. 非自己持有的对象自己无法释放. 而 ARC 则是帮助我们

[share]深入探讨PHP中的内存管理问题

一. 内存 在PHP中,填充一个字符串变量相当简单,这只需要一个语句"<?php $str = "hello world "; ?>"即可,并且该字符串能够被自由地修改.拷贝和移动.而在C语言中,尽管你能够编写例如"char *str = "hello world ";"这样的一个简单的静态字符串:但是,却不能修改该字符串,因为它生存于程序空间内.为了创建一个可操纵的字符串,你必须分配一个内存块,并且通过一个函数(

通过案例深入探讨PHP中的内存管理问题

问题  内存管理对于长期运行的程序,例如服务器守护程序,是相当重要的影响:因此,理解PHP是如何分配与释放内存的对于创建这类程序极为重要.本文将重点探讨PHP的内存管理问题. 一. 内存 在PHP中,填充一个字符串变量相当简单,这只需要一个语句"<?php $str = 'hello world '; ?>"即可,并且该字符串能够被自由地修改.拷贝和移动.而在C语言中,尽管你能够编写例如"char *str = "hello world ";&

深入探讨PHP中的内存管理问题

摘要 内存管理对于长期运行的程序,例如服务器守护程序,是相当重要的影响:因此,理解PHP是如何分配与释放内存的对于创建这类程序极为重要.本文将重点探讨PHP的内存管理问题. 一. 内存 在PHP中,填充一个字符串变量相当简单,这只需要一个语句"<?php $str = 'hello world '; ?>"即可,并且该字符串能够被自由地修改.拷贝和移动.而在C语言中,尽管你能够编写例如"char *str = "hello world ";&q

PHP 内存管理器符号比较多个溢出漏洞

受影响系统:PHP PHP 5.2.0 不受影响系统:PHP PHP 5.2.1 描述:BUGTRAQ ID: 23238 PHP是广泛使用的通用目的脚本语言,特别适合于Web开发,可嵌入到HTML中.PHP的内存管理器实现上存在漏洞,本地攻击者可能利用此漏洞提升权限.如果通过emalloc()函数分配内存的话,PHP中新的Zend内存管理器会在内部的_zend_mm_alloc_int()函数中处理这个请求,首先使用ZEND_MM_TRUE_SIZE宏判断所请求内存块的真实大小,如下所示: s

Java实时应用程序中的内存管理

使用Java的一个主要优点就是无需担心废弃对象,即,让Java运行时负责Java对象的内存管理. 这是通过让Java运行时对不再使用的Java对象进行垃圾收集而实现的. 垃圾收集是一个比较复杂的过程.通常,Java运行时会遍历堆,检查不再被其他对象引用.从而可以安全删除的对象,然而,由于垃圾收集占用CPU周期,所以它可能会影响应用程序代码的执行.即,如果在执行应用程序代码的过程中执行垃圾收集,则应用程序代码的响应时间可能延长.这会导致用户事务延迟的延长.更为糟糕的是,因为用户不知道何时会进行垃圾