zoukankan      html  css  js  c++  java
  • 数据库数据在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位, 64JVMJDK1.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里转换为HashMapEmp对象測试空间例如以下

     

    对象

    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须要68KBemp对象须要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;
            }
        }
    }
    



  • 相关阅读:
    题解:艾米利亚的魔法
    tarjan求割点
    集合删数
    小测题解
    [考试]20141028
    铺地毯
    [考试]20141027
    大家好
    【DM642学习笔记一】关于Can't Initialize Target CPU的一种解决方法 : Error 0x80000240
    iOS开发之获取系统相册ALAssetLibrary
  • 原文地址:https://www.cnblogs.com/lytwajue/p/7116975.html
Copyright © 2011-2022 走看看