数据库数据在Java占用内存简单估算
数据库数据在Java占用内存简单估算
结论:
1.数据库记录放在JAVA里,用对象(ORM一般的处理方式)须要4倍左右的内存空间。用HashMap这样的KV保存须要10倍空间;
2.假设你主要数据是text大文本,那空间一般能够按2倍估算。
以上是一个通用数据測试结论。估大家參考。
数据库记录占用的空间大小比較好算,比方一个int占用4字节。bigint占用8字节。date占用3字节,datetime占用8字节,varchar是变长字节等。假设不想精确计算,在数据库中通过统计信息也能够比較轻松的知道表总共占用的空间及每条记录平均行长。
当我们用JDBC訪问数据库时。常常会被问到内存溢出的问题。因为java是面向对象的语言。用JVM来自己主动内存回收。不能按普通方法计算内存,本文给出一个估算内存的思路和參考答案
先给出普通JDBC中数据库对象与内存的映射关系
|
MySQL |
Oracle |
JDBC |
|
Int |
Integer |
|
|
Int unsigned |
Long |
|
|
BigInt |
Long |
|
|
BigInt unsigned |
BigInteger |
|
|
Decimal |
Number |
BigDecimal |
|
Varchar |
Varchar2 |
String |
|
Date |
Date |
|
|
Datetime |
Date |
Timestamp |
|
Timestamp |
Timestamp |
Timestamp |
|
Clob |
Clob |
String |
|
Blob |
blob |
Byte[] |
|
Text |
Clob |
String |
|
float |
binary_float |
float |
|
double |
binary_double |
double |
上面这个比較好理解,接下来我们须要JAVA经常使用对象的内存占用空间,这个能够通过JDK 5 開始提供的Instrumentation 接口来完毕,也能够通过开源的sizeOf.jar 来測试。笔者是通过sizeOf.jar验证的。測试结果数据例如以下:
|
对象 |
64位 JVM 压缩指针 |
64位 JVM 非压缩指针 |
|
Integer |
16 |
24 |
|
Long |
24 |
24 |
|
Object |
16 |
16 |
|
Date |
24 |
32 |
|
Timestamp |
32 |
40 |
|
String_0 |
48 |
64 |
|
String_1 |
56 |
72 |
|
String_10 |
72 |
88 |
|
String_100 |
248 |
264 |
|
StringBuilder |
24 |
32 |
|
BigDecimal |
40 |
48 |
|
BigInteger |
64 |
80 |
|
HashMap |
128 |
216 |
|
HashMap_0 |
72 |
96 |
|
HashMap_100 |
576 |
1112 |
|
HashMap_10000 |
65600 |
131160 |
|
ArrayList |
80 |
144 |
|
ArrayList_0 |
40 |
64 |
|
ArrayList_100 |
440 |
864 |
|
ArrayList_10000 |
40040 |
80064 |
|
LinkedList |
48 |
80 |
|
LinkedHashMap |
96 |
144 |
|
ClassA |
32 |
40 |
|
ClassB |
40 |
48 |
|
ClassC |
40 |
56 |
因为如今主机一般都是64位, 64位JVM从JDK1.6.45開始,当JVM最大内存小于32GB时,自己主动打开压缩指针特性。这样对象的内存占用空间少非常多,由上表能够看出。至少降低1/3的空间。
以下我们结合数据库数据来測试
假如mysql数据库有一张emp表,结构例如以下:
CREATE TABLE `emp` (
`id` int(11) NOT NULL,
`create_time` datetime DEFAULT NULL,
`modify_time` datetime DEFAULT NULL,
`name` varchar(16) DEFAULT NULL,
`address` varchar(256) DEFAULT NULL,
`age` smallint(6) DEFAULT NULL,
`height` decimal(10,2) DEFAULT NULL,
`weight` decimal(10,2) DEFAULT NULL,
`phone` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
样本数据例如以下:
hm.put("id", 1988);
hm.put("createTime", new Date());
hm.put("modifyTime", new Date());
hm.put("name", "张三丰");
hm.put("address","浙江杭州市西湖大道188号808室");
hm.put("age",88);
hm.put("weight",new BigDecimal(88));
hm.put("height",new BigDecimal(188));
hm.put("phone","1388888888");
按上面样本数据计算,有效数据约80字节。在MySQL里占用空间约120字节
在java里转换为HashMap和Emp对象測试空间例如以下
|
对象 |
64位 JVM 压缩指针 |
64位 JVM 非压缩指针 |
|
HashMap_empty |
128 |
216 |
|
HashMap_full |
1360 |
1832 |
|
Emp_empty |
72 |
112 |
|
Emp_full |
464 |
600 |
从上面測试结果看。数据到JAVA里占用的空间添加了很多,在64位压缩指针下,假设存到HashMap,须要1360字节,空间是数据库约11.3倍,假设存为Emp普通对象,须要464字节,是数据库的3.8倍。
假设我们是一个分页从数据库读取emp信息,每页显示50条记录,用List保存。HashMap须要68KB。emp对象须要23KB。
依据这个简单測试,我们能够总结一个结论:
数据库记录放在JAVA里,用对象(ORM一般的处理方式)须要4倍左右的内存空间。用HashMap这样的KV保存须要10倍空间。
假设你的数据和參考数据差异很大,如主要数据text大文本,那空间一般能够简单的按2倍估算。
以上是一个通用数据測试结论。估大家參考。
以下是測试代码:
import net.sourceforge.sizeof.SizeOf;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.*; public class TestSize {
static {
SizeOf.skipStaticField(true); //java.sizeOf will not compute static fields
//SizeOf.skipFinalField(true); //java.sizeOf will not compute final fields
//SizeOf.skipFlyweightObject(true); //java.sizeOf will not compute well-known flyweight objects
}
public static void main(String[] args) throws SQLException, IOException, IllegalAccessException {
TestSize ts=new TestSize();
ts.testObjectSize();
ts.testDataSize();
System.out.println("ok");
} public void testObjectSize() {
System.out.println("Integer:"+SizeOf.deepSizeOf(new Integer(56)));
System.out.println("Long:"+SizeOf.sizeOf(new Long(56L)));
System.out.println("Object:"+SizeOf.sizeOf(new Object()));
System.out.println("Date:"+SizeOf.sizeOf(new Date()));
System.out.println("Timestamp:"+SizeOf.sizeOf(new Timestamp(System.currentTimeMillis())));
System.out.println("String_0:"+SizeOf.deepSizeOf(new String()));
System.out.println("String_1:"+SizeOf.deepSizeOf(new String("1")));
System.out.println("String_10:"+SizeOf.deepSizeOf(new String("0123456789")));
System.out.println("String_100:"+SizeOf.deepSizeOf("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"));
System.out.println("StringBuilder:"+SizeOf.deepSizeOf(new StringBuilder()));
System.out.println("BigDecimal:"+SizeOf.deepSizeOf(new BigDecimal("34535643.23")));
System.out.println("BigInteger:"+SizeOf.deepSizeOf(new BigInteger("34535643")));
System.out.println("HashMap:"+SizeOf.deepSizeOf(new HashMap()));
System.out.println("HashMap_0:"+SizeOf.deepSizeOf(new HashMap(0)));
System.out.println("HashMap_100:"+SizeOf.deepSizeOf(new HashMap(100)));
System.out.println("HashMap_10000:" + SizeOf.deepSizeOf(new HashMap(10000)));
System.out.println("ArrayList:"+SizeOf.deepSizeOf(new ArrayList()));
System.out.println("ArrayList_0:"+SizeOf.deepSizeOf(new ArrayList(0)));
System.out.println("ArrayList_100:"+SizeOf.deepSizeOf(new ArrayList(100)));
System.out.println("ArrayList_10000:"+SizeOf.deepSizeOf(new ArrayList(10000)));
System.out.println("LinkedList:"+SizeOf.deepSizeOf(new LinkedList<Object>()));
System.out.println("LinkedHashMap:"+SizeOf.deepSizeOf(new LinkedHashMap<Object,Object>())); System.out.println("ClassA:" + SizeOf.deepSizeOf(new ClassA()));
System.out.println("ClassB:"+SizeOf.deepSizeOf(new ClassB()));
System.out.println("ClassC:"+SizeOf.deepSizeOf(new ClassC())); }
public void testDataSize() throws IOException, IllegalAccessException {
HashMap hm=new HashMap();
System.out.println("HashMap_empty:"+SizeOf.deepSizeOf(hm));
hm.put("id", 1988);
hm.put("createTime", new Date());
hm.put("modifyTime", new Date());
hm.put("name", "张三丰");
hm.put("address","浙江杭州市西湖大道188号808室");
hm.put("age",88);
hm.put("weight",new BigDecimal(88));
hm.put("height",new BigDecimal(188));
hm.put("phone","1388888888");
System.out.println("HashMap_full:" + SizeOf.deepSizeOf(hm));
Emp emp=new Emp();
System.out.println("Emp_empty:"+SizeOf.deepSizeOf(emp));
emp.setId(1988);
emp.setCreateTime(new Timestamp(System.currentTimeMillis()));
emp.setModifyTime(new Timestamp(System.currentTimeMillis()));
emp.setName("张三丰");
emp.setAddress("浙江杭州市西湖大道188号808室");
emp.setAge(28);
emp.setWeight(new BigDecimal("88"));
emp.setHeight(new BigDecimal("188"));
emp.setPhone("13888888888");
System.out.println("Emp_full:"+SizeOf.deepSizeOf(emp));
}
class ClassA{
}
class ClassB extends ClassA{
}
class ClassC extends ClassB{
}
class Emp{
private Integer id;
private Timestamp createTime;
private Timestamp modifyTime;
private String name;
private String address;
private Integer age;
private BigDecimal height;
private BigDecimal weight;
private String phone; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public Timestamp getCreateTime() {
return createTime;
} public void setCreateTime(Timestamp createTime) {
this.createTime = createTime;
} public Timestamp getModifyTime() {
return modifyTime;
} public void setModifyTime(Timestamp modifyTime) {
this.modifyTime = modifyTime;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public BigDecimal getHeight() {
return height;
} public void setHeight(BigDecimal height) {
this.height = height;
} public BigDecimal getWeight() {
return weight;
} public void setWeight(BigDecimal weight) {
this.weight = weight;
} public String getPhone() {
return phone;
} public void setPhone(String phone) {
this.phone = phone;
}
}
}
数据库数据在Java占用内存简单估算的更多相关文章
- php 因循环数据 赋值变量 占用内存太大 提示错误
Fatal error: Allowed memory size of 134217728 bytes exhausted 网上很多解决方法:就简单记录下 一个csv导入功能 由于数据太多 占用内存太 ...
- 关于Java占用内存的研究
最近对程序占用内存方面做了一些优化,取得了不错的效果,总结了一些经验简要说一下,相信会对大家写出优质的程序有所帮助下面的论述针对32位系统,对64位系统不适用,后叙 经常你写了一个程序,一测试,功能没 ...
- 查看java进程内存简单示例
分析工具 1.jps 显示指定系统内的所有JVM进程 2.jstat 收集JVM各方面的运行数据 3.jinfo 显示JVM配置信息 4.jmap 堆快照 5.jhat 分析headdump文件 ...
- java构造器级简单内存分析
java构造器的使用(基础篇) 构造方法也叫构造器,是创建对象时执行的特殊方法,一般用于初始化新对象的属性. 基本定义语法: 访问控制符 构造方法名([参数列表]){ 方法体 } 注:"访问 ...
- Delphi数据库数据用文件流方式快速写入Excel文件
在开发数据库应用程序中,经常要将类型相同的数据导出来,放到Excel文件中,利用Excel强大的编辑功能,对数据作进一步的加工处理.这有许多的方法,我们可以使用OLE技术,在Delphi中创建一个自动 ...
- JVM基础系列第6讲:Java 虚拟机内存结构
看到这里,我相信大家对于一个 Java 源文件是如何变成字节码文件,以及字节码文件的含义已经非常清楚了.那么接下来就是让 Java 虚拟机运行字节码文件,从而得出我们最终想要的结果了.在这个过程中,J ...
- 使用Java编写一个简单的Web的监控系统cpu利用率,cpu温度,总内存大小
原文:http://www.jb51.net/article/75002.htm 这篇文章主要介绍了使用Java编写一个简单的Web的监控系统的例子,并且将重要信息转为XML通过网页前端显示,非常之实 ...
- Java程序内存分析:使用mat工具分析内存占用
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- docker容器内存占用 之 系统cache,docker下java的内存该如何配置
缘起: 监控(docker stats)显示容器内存被用完了,进入容器瞅了瞅,没有发现使用内存多的进程,使用awk等工具把容器所有进程使用的内存加起来看看,距离用完还远了去了,何故? 分析: 该不会d ...
随机推荐
- JavaScript判断
if...else: if...else语句是在指定的条件成立时执行的代码,在条件不成立时执行else后的代码. 语法: if(条件) {条件成立时执行的代码 }else{ 条件不成立的时执行的代码} ...
- 6.14 提取第n个分割的子串
问题:从字符串中提取出一个指定的.由分割符隔开的子字符串.create view v as select 'mo,larry,curly' as namefrom t1union allselect ...
- jmeter 常见问题一(url重定向)
刚接触JMeter,想把学习过程中遇到的一些问题,记录下来因为是新接触,所以很多东西都在摸索中! 使用Badboy录制了公司一个项目的登录功能导入到JMeter后,执行场景,发现登录校验成功,但后续的 ...
- 梦想CAD控件关于标注的系统变量说明
主要用到函数说明: IMxDrawDimension::SetDimVarDouble 设置标注属性的实数类型变量值,详细说明如下: 参数 说明 [in] LONG iType 该属性的类形值 dVa ...
- 02C语言基本语法
C语言基本语法 注释 //行注释 /* 块注释*/ 标识符 标识符是用来标识变量.函数.任何其他用户自定义项目的名称:一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母.下划 ...
- 若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet(转载)
若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet 若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet 请将 J ...
- BZOJ2657: [Zjoi2012]旅游(journey) (树形DP)
题意:一个三角划分的凸多边形 画一条对角线 穿过最多的三角形 题解:把每一个三角形看作一个点 如果某条边是两个三角形的公共边 那么就把这两个三角形连边 然后问题就转化为求树上的最长链了 就当求个直径就 ...
- 【Js 文件】 相关
防止浏览器缓存 <script src="/js/common.js?t=<%=DateTime.Now.ToFileTime().ToString()%>>&quo ...
- Python Web开发
参考原文 Python廖雪峰 WSGI接口 WSGI(Web Server Gateway Interface)是一个接口,用来屏蔽底部的细节(如TCP的建立连接,HTTP原始请求和响应格式等).WS ...
- 诊断:expdp导出时遇到错误ORA-31693和ORA-00922
11.2.0.1使用数据泵expdp导出时,如果使用parallel,可能会遇到 ORA-: Table data object "OWNER"."TABLE" ...