数据库数据在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 ...
随机推荐
- Java线程及Jvm监控工具
Java线程状态 线程的五种状态 * 新建:new(时间很短) * 运行:runnable * 等待:waitting(无限期等待),timed waitting(限期等待) * 阻塞:blocked ...
- 接口与抽象类的区别-Java
概念-抽象类: 类是对某一个对象的具体描述,抽象类则是对有共通之处的对象,描述共通之处的类;包含抽象方法的类一定的抽象类,抽象类并不一定包含抽象方法;抽象类中可以有数据成员,但数据成员必须是stati ...
- 并发编程学习笔记(6)----公平锁和ReentrantReadWriteLock使用及原理
(一)公平锁 1.什么是公平锁? 公平锁指的是在某个线程释放锁之后,等待的线程获取锁的策略是以请求获取锁的时间为标准的,即使先请求获取锁的线程先拿到锁. 2.在java中的实现? 在java的并发包中 ...
- 13Oracle Database 存储过程
Oracle Database 存储过程 触发器相当于java中的事件监听,当某事件发生时激活特定的事件并执行相应的逻辑 DML触发器中包含了三种事件 insert update delete 语法格 ...
- Android studio 开发一个用户登录界面
Android studio 开发一个用户登录界面 activity_main.xml <?xml version="1.0" encoding="utf-8&qu ...
- Linux kernel 内存 - 页表映射(SHIFT,SIZE,MASK)和转换(32位,64位)
0. Intro 如下是在32位下的情况,32位下,只有三级页表:PGD,PMD,PTE 在64位情况下,会有四级页表:PGD,PUD,PMD,PTE 但是原理基本上是一样的,本文主要是想记录一下页表 ...
- dorado 7 使用总结
最近项目上需要,使用了dorado 7 ,总体感觉还可以,快速开发很方便,然而在方便的同时,难免有些太过繁琐,很多东西都封装了起来,会造成很多不便.因此快速开发的项目可以使用,其它的不推荐.现在打算将 ...
- SIMD学习 -- 用SSE2指令作点乘和累加计算
这几天在做学校的一个学习小项目,需要用到SIMD指令计算提速.也是第一次碰这个,看了一些资料和代码,模仿着写了两个函数. void sse_mul_float(float *A, float *B, ...
- Gym - 101670E Forest Picture (CTU Open Contest 2017 模拟)
题目: https://cn.vjudge.net/problem/1451310/origin 题意&思路: 纯粹模拟. 大体题意是这样的: 1.有人要在一个10-9<=x<=1 ...
- Codeforces 934D/933B - A Determined Cleanup
传送门:http://codeforces.com/contest/934/problem/D 给定两个正整数p(p≥1).k(k>1).多项式f(x)的系数的取值集合为{0,1,2,...,k ...