2012-11-22 4 views
3

가능한 한 빨리 Tomcat의 HSQLDB에 1.000.000 개의 항목을 삽입해야하지만이 코드에는 64m (Tomcat의 기본 MaxPermSize)가 충분하지 않아서 "OutOfMemoryError"가 발생합니다 (원하는 경우 기본 설정에 삽입).HSQLDB 최적화 1.000.000 벌크 삽입

connection.setAutoCommit(false); 
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO USER (firstName, secondName) VALUES(?,?)"); 
for (int i = 0; i < 1000000; i++) { 
    preparedStatement.setString(1, "firstName"); 
    preparedStatement.setString(2, "secondName"); 
    preparedStatement.addBatch(); 
} 
preparedStatement.executeBatch(); 
connection.commit(); 

나는 이것을 http://hsqldb.org/doc/2.0/guide/deployment-chapt.html#dec_bulk_operations으로 바꿨다. "SET FILES LOG FALSE"를 설정했지만 도움이되지 않습니다.

  1. MaxPermSize = 64m 인 1.000.000 항목을 삽입하는 방법이 있습니까?
  2. 왜이 코드에 tomcat이 많은 메모리를 먹나요? 1.000.000 * 19 ("firstName"+ "secondName"길이) * 2 (1 심볼상의 바이트) = ~ 40MB.
  3. 왜 메모리 테이블에서 삽입이 더 빨리 캐시 된 테이블로 이동합니까? 내가 뭔가 잘못하고 있는거야?
+1

10000 배치 크기로 삽입 할 수 있습니까? 모든 1M 항목을 1 배치에 삽입해야합니까? – nhahtdh

+0

예 시도했지만 여전히 작동하지 않았습니다. 아무리 많은 배치가 있더라도 상관 없습니다. – mnemosha

+2

'String' 객체의 메모리 점유는 문자열의 길이에 2를 곱한 길이 인 약 40 바이트를 더한 것입니다.이 경우 약 19 (문자열의 길이) + 40 = 각 문자열의 59 바이트, 즉 118 바이트 * 1000000 = ~ 118MB. 그래서 가장 좋은 해결책은 @nhahtdh에 의해 지적 된 바와 같이 더 작은 배치를 사용하는 것입니다. – remigio

답변

4
  1. 더 작은 세트로 시도해보십시오. 그것은 적은 메모리를 소비하고 아마도 더 효율적일 것입니다.
  2. 메모리 크기를 계산하는 것이 훨씬 더 어렵습니다. 예를 들어 firstName에 100 만 시간을 저장하지 않아도 값이 내부화되지만 참조를 100 만 회 저장해야합니다. 그런 다음 모든 라이브러리에서 메모리 등을 사용합니다.
  3. "캐시 된 테이블"은 무엇이라고합니까?

그 시도, 적은 메모리를 사용합니다 적어도 :

connection.setAutoCommit(false); 
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO USER (firstName, secondName) VALUES(?,?)"); 
for (int i = 0; i < 1000000; i++) { 
    preparedStatement.setString(1, "firstName"); 
    preparedStatement.setString(2, "secondName"); 
    preparedStatement.addBatch(); 
    if(i % 1000 == 0) 
     preparedStatement.executeBatch(); 
} 
preparedStatement.executeBatch(); 
connection.commit(); 

편집 : 당신은 확실이 때문에 파마 크기입니까? 스택 트레이스를 넣을 수 있습니까?

+0

if 문에서 executeBatch() 후 커밋이 더 좋을 것이라고 생각합니다. – chrome

+1

당신이 저지른다면 당신은 저 지르지 않을 것입니다. 커밋은 DB의 기능이므로 DB의 메모리에만 영향을 미쳐야합니다. 그러나 임베디드 DB이기 때문에 아마도 옳을 것이다. 메모리를 절약 할 것이다. 하지만 커밋을 할 때 반복합니다. – tibo

+0

메모리 사용을 줄이기 위해서는 주기적으로 커밋해야합니다. 그렇지 않으면 모든 1000000 행은 커밋 될 때까지 메모리에 보관됩니다. – fredt