데이터베이스 데이터 가 자바 에서 차지 하 는 메모리 에 대한 간단 한 추산

11348 단어
데이터베이스 데이터 가 자바 에서 차지 하 는 메모리 에 대한 간단 한 추산
 
결론:
1. 데이터 베 이 스 를 JAVA 에 기록 하고 대상 (ORM 일반적인 처리 방식) 으로 4 배 정도 의 메모리 공간 이 필요 하 며 HashMap 과 같은 KV 로 저장 하려 면 10 배 공간 이 필요 합 니 다.
2. 주요 데이터 가 text 큰 텍스트 라면 공간 은 보통 2 배로 계산 할 수 있 습 니 다.
이상 은 통용 데이터 테스트 결론 이 므 로 여러분 이 참고 하 시기 바 랍 니 다.
 
데이터베이스 기록 이 차지 하 는 공간 크기 는 비교적 계산 하기 쉽다. 예 를 들 어 하나의 int 는 4 바이트, bigint 는 8 바이트, date 는 3 바이트, datetime 은 8 바이트, varchar 는 길 어 지 는 바이트 등 이다.정확하게 계산 하지 않 으 려 면 데이터 베이스 에서 통계 정 보 를 통 해 표 가 모두 차지 하 는 공간 과 모든 기록 의 평균 행장 을 쉽게 알 수 있다.
 
JDBC 로 데이터 베 이 스 를 방문 할 때 메모리 가 넘 치 는 질문 을 자주 받 습 니 다. 자바 는 대상 을 대상 으로 하 는 언어 이기 때문에 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 은 JDK 1.6.45 부터 JVM 의 최대 메모리 가 32GB 보다 적 을 때 자동 으로 압축 포인터 기능 을 켜 면 대상 의 메모리 사용 공간 이 매우 적 고 위의 표 에서 볼 수 있 듯 이 최소 1 / 3 의 공간 이 줄어든다.
 
다음은 데이터베이스 데 이 터 를 결합 하여 테스트 하 겠 습 니 다.
만약 my sql 데이터베이스 에 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 바이트 의 공간 을 차지한다.
자바 에서 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 에 저장 하려 면 데이터베이스 의 약 11.3 배 인 1 천 360 바이트 가 필요 하 며, Emp 일반 대상 으로 저장 하려 면 데이터베이스 의 3.8 배 인 464 바이트 가 필요 하 다.
 
데이터베이스 에서 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;
        }
    }
}

좋은 웹페이지 즐겨찾기