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中的容量。

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

目录
相关文章
|
7月前
|
SQL Java 关系型数据库
定位频繁创建对象导致内存溢出风险之JDBC MySQL
定位频繁创建对象导致内存溢出风险之JDBC MySQL
181 0
|
9月前
|
存储 SQL 缓存
MySQL高级第三篇(共四篇)之应用优化、查询缓存优化、内存管理优化、MySQL锁问题、常用SQL技巧(二)
锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。 在数据库中,除传统的计算资源(如 CPU、RAM、I/O 等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。
369 0
|
9月前
|
SQL 存储 缓存
MySQL高级第三篇(共四篇)之应用优化、查询缓存优化、内存管理优化、MySQL锁问题、常用SQL技巧(一)
前面章节,我们介绍了很多数据库的优化措施。但是在实际生产环境中,由于数据库本身的性能局限,就必须要对前台的应用进行一些优化,来降低数据库的访问压力。
15969 7
|
存储 Java 关系型数据库
MySQL 驱动中虚引用 GC 耗时优化与源码分析
MySQL 驱动中虚引用导致 GC 耗时较长问题的解决方法、虚引用的作用与使用场景、MySQL 驱动源码中的虚引用分析。
250 0
MySQL 驱动中虚引用 GC 耗时优化与源码分析
|
程序员
性能优化反思:减少DB查询,合理使用成员变量
高内聚,低耦合是非常深入人心的设计思想,在做到高内聚低耦合的同时,我们也要考虑到值传递的问题:要避免在抽取函数,封装代码时不合理的值传递,避免在多个函数内部重复查询相同的DB
|
SQL Oracle NoSQL
JDK的sql设计不合理导致的驱动类初始化死锁问题
JDK的sql设计不合理导致的驱动类初始化死锁问题
JDK的sql设计不合理导致的驱动类初始化死锁问题
|
MySQL 关系型数据库 索引
mysql中order by 和limit一起使用不当会导致效率极慢的4种优化方法
今天从慢查询发现一条语句查询时间达6秒。结果只查出一条记录。 原语句如下 SELECT biz_order_id, buyer_id, buyer_nick, item_id, item_name, total_price, buy_amount, pay_status, STATUS, att.
11177 0
|
Java 关系型数据库 数据库连接