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

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

目录
相关文章
|
SQL 监控 Java
如何避免JDBC池和内存溢出?优化策略大揭秘!
0 目标 生成订单接口的基准场景是什么结果。 SQL的问题定位
526 0
|
关系型数据库 大数据 MySQL
mysql jdbc读取大数据出现内存溢出
useCursorFetch=true&defaultFetchSize=100
3693 0
|
28天前
|
Java 关系型数据库 MySQL
mysql5.7 jdbc驱动
遵循上述步骤,即可在Java项目中高效地集成MySQL 5.7 JDBC驱动,实现数据库的访问与管理。
106 1
|
1月前
|
SQL 分布式计算 关系型数据库
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-24 Sqoop迁移 MySQL到Hive 与 Hive到MySQL SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
84 0
|
1月前
|
SQL 分布式计算 关系型数据库
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-23 Sqoop 数据MySQL到HDFS(部分) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
37 0
|
1月前
|
SQL 分布式计算 关系型数据库
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
Hadoop-22 Sqoop 数据MySQL到HDFS(全量) SQL生成数据 HDFS集群 Sqoop import jdbc ETL MapReduce
46 0
|
3月前
|
SQL druid Java
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下)
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)
55 3
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下)
|
3月前
|
SQL Java 关系型数据库
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(上)
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)
118 3
Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(上)
|
3月前
|
前端开发 关系型数据库 MySQL
com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver 的区别
这篇文章讨论了`com.mysql.jdbc.Driver`和`com.mysql.cj.jdbc.Driver`两个MySQL驱动类的区别,指出`com.mysql.jdbc.Driver`适用于MySQL 5的`mysql-connector-java`版本,而`com.mysql.cj.jdbc.Driver`适用于MySQL 6及以上版本的`mysql-connector-java`。文章还提到了在实际使用中如何根据MySQL版本选择合适的驱动类。
com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver 的区别