数据库数据在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;
        }
    }
}
时间: 2024-11-11 17:40:48

数据库数据在Java占用内存简单估算的相关文章

jsp连接数据库显示数据库数据、java连接数据库调用数据。

JSP直接调用数据库,需要数据库连接相关jar包: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.sql.*"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transi

Java程序内存分析:使用mat工具分析内存占用

在工作中可能会遇到内存溢出这种灾难性的问题,那么程序肯定是存在问题,找出问题至关重要,上一篇文章讲了jmap命令的使用方法,当然用jmap导出的文件我们也看不懂啊,那就交给memory analyzer(mat)这个工具,让他帮助我们来观察程序的内存分布情况吧. 1. 用jmap生成堆信息 2. 将堆信息导入到mat中分析 3. 生成分析报告 Histogram Dominator Tree Top consumers Leak Suspects MAT 不是一个万能工具,它并不能处理所有类型的

new Java对象占用内存分析

最近在读<深入理解Java虚拟机>,对Java对象的内存布局有了进一步的认识,于是脑子里自然而然就有一个很普通的问题,就是一个Java对象到底占用多大内存? 在网上搜到了一篇博客讲的非常好:http://yueyemaitian.iteye.com/blog/2033046,里面提供的这个类也非常实用: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

solr 简单搭建 数据库数据同步(待续)

原来在别的公司负责过文档检索模块的维护(意思就是不是俺开发的啦).所以就稍微接触和研究了下文档检索. 文档检索其实是全文检索,是通过一种技术把N多文档进行一定规律的切割归类,然后创建易于搜索的索引式文件,然后搜索具有某些规律的文档时,能够通过快速定位索引,然后根据索引提供的信息精确定位到文档从而实现迅速找到文档.这个文档一般成为条目. 上家公司的时候使用的是Lucene加上Zoie实现的.lucene是apache下的开源项目,不过并不是全文检索的实现,而是一个全文检索的引擎,是一个架构,是其他

Java将数据库数据导入EXCEL

一般的数据库数据怎么导入excel中呢??这让人非常疑惑,今天我找到了一个方法能够实现 须要导入一个第三方包下载地址 详细内容例如以下: 里面含有指导文档,index.html里面含有怎样读取数据库文件到excel和excel数据到数据库中. 主要用到一个包 将这个包复制到项目里面就能够了. 先做一个简单版本号的helloword <span style="white-space:pre"> </span>public void mkexcel() throws

数据库中树结构数据,转换为Java对象树结构( 多叉树结构 )

总体就是图所表示所表示的转换,由数据库 => Java对象转换,代码比较简单,但对数据库压力可以大一点,多次查询. 主要是对象之间建立关联 No.2 : MapToTree() 思路为: 用pid(父id)作分组 ,这样每一个组的父节点是同一样,换句话说就是同一分组里,所有节点pid是相同的. 这样就针对分组操作,建立关联. 用Map做封装,key为父ID, value为分组List 用到了QueryRunner 这个是数据库工具,只要在网上找,下载就可以,能直接查询List. QueryRun

java优化占用内存的方法(一)

java做的系统给人的印象是什么?占 内存!说道这句话就会有N多人站出来为java辩护,并举出一堆的性能测试报告来证明这一点.其实从理论上来讲java做的系统并不比其他语言开发出来的 系统更占用内存,那么为什么却有这么N多理由来证明它确实占内存呢?两个字,陋习.(1)别用new Boolean().在很多场景中Boolean类型是必须的,比如JDBC中boolean类型的set与get都是通过Boolean封装传递的,大部分ORM也是用Boolean来封装boolean类型的,比如:ps.set

JAVA对象是如何占用内存的

本文使用的是32位的JVM ,jdk1.6.本文基本是翻译的,加上了一些自己的理解,原文见文章底下链接. 在本文中,我们讨论如何计算或者估计一个JAVA对象占多少内存空间.(注意,使用 Classmexer agent 或者VM insturmentation 可以查询到一个java对象占用了多少内存.) 一般来说,我们讨论一个在堆中的对象的内存,前提是在“正常状态”下.我们忽略下面两种情况. 在某些情况下,JVM 不一定会把对象放到堆中.例如,一个简单的线程本地对象可以存放在栈中. 一个对象占

Java读取数据库数据生成柱状图

此案例是用swing显示数据的.需要引入jfreechart相关包,不同版本可能包不相同,本人用的是 此案例在ssi框架下会报错,不用框架就没问题. Java后台逻辑代码: public class BarChart { ChartPanel frame1; public BarChart() { CategoryDataset dataset = getDataSet(); JFreeChart chart = ChartFactory.createBarChart3D("水果",