数据库数据在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 ...
随机推荐
- Rxjava1升级Rxjava2踩坑一记
Rxjava1升级Rxjava2坑 共存问题 通常情况下,如果我们希望在一个模块中既想使用rxjava1又想使用rxjava2,这个时候在运行的时候会出现一下报错: ... APK META/-INF ...
- Activity随笔
Activity的生命周期 1.正常情况下的生命周期 onCreate: Activity正在被创建,生命周期中的第一个方法,常在此方法中做一些初始化工作,比如调用setContentView方法, ...
- ubuntu系统nginx+Redis+PHP
一.安装ngnix apt-get update sudo apt-get install nginx /etc/init.d/nginx start 二.安装php sudo apt-get ins ...
- 梦想CAD控件图层COM接口知识点
梦想CAD控件图层COM接口知识点 一.新建图层 主要用到函数说明: _DMxDrawX::AddLayer 增加新的图层.详细说明如下: 参数 说明 BSTR pszName 图层名 c#中实现代码 ...
- 【nginx】解决nginx搭建图片服务器访问图片404
图片通过ftp服务上传到/home/ftpuser/www/images目录下后访问 http://192.168.128.128/images/xxx.jpg 还是 404 NOT FOUND ,解 ...
- A1. JVM 内存区域
[概述] 在这篇笔记中,需要描述虚拟机中的内存是如何划分的,哪部分区域.什么样的代码和操作可能导致内存溢出异常.虽然 Java 有垃圾处理机制,但是如果生产环境在出现内存溢出异常时,由于开发人员不熟悉 ...
- SQL删除重复数据(根据多个字段),pandas的nan存入数据库报错
delete from M_FACTOR_DATA_TEST a where (a.factor_id,a.data_date,a.stock_code) in (select factor_id,d ...
- Colletions工具类常用方法
Collections 工具类常用方法: 排序 查找,替换操作 同步控制(不推荐,需要线程安全的集合类型时请考虑使用 JUC 包下的并发集合 排序操作 void reverse(List list)/ ...
- NOIP2016 DAY1 T2天天爱跑步
传送门 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 ...
- 随机数生成工具类(中文姓名,性别,Email,手机号,住址)
public class RandomValueUtil { public static String base = "abcdefghijklmnopqrstuvwxyz012345678 ...