개발자

COPY(PG) GC 오버헤드 에러

2024년 04월 13일조회 85

안녕하세요. 대용량의 텍스트 파일을 postgreSql에 적재하는 모듈을 개발하고 있습니다. copy 함수를 활용하여 텍스트 파일('|'으로 구분되어 있는)을 테이블에 insert 하는데 헤더 스킵을 위해 csv로 parsing하려고 합니다. 근데 파일이 커서 그런가(8GB정도) 'OutOfMemoryError : gc overhead limit exceeded' 에러가 계속 발생합니다.. (어떨 땐 에러 없이 잘 들어가기도 합니다) 코드 중에 불필요한 구문이 있는 건지 판단이 잘 안됩니다... 또 csv로 파싱하지 않고 텍스트 파일의 첫째 줄을 지우고 copy로 밀어 넣는 방법이 있을까요? --------구현 코드-------- try ( BaseConnection c = dataSource.getConnection().unwrap(BaseConnection.class)) { try ( PGCopyOutputStream os = new PGCopyOutputStream(c, "COPY " + tableName + " FROM STDIN WITH (FORMAT CSV)"); CSVPrinter writer = new CSVPrinter(new OutputStreamWriter(os, StandardCharsets.UTF_8), CSVFormat.POSTGRESQL_CSV); CSVParser reader = new CSVParser(new InputStreamReader(inputStream, charset), CSVFormat.INFORMIX_UNLOAD.withFirstRecordAsHeader())) { for (CSVRecord row : reader) { for (String col : row) { if (col != null && StringUtils.hasText(col.trim())) { writer.print(col.trim()); } else { writer.print(null); } } writer.println(); } } } *inputStream은 해당 파일 BufferedInputStream 객체입니다.

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 1

안희수님의 프로필 사진

기본적으로는 스트림 객체는 사용이 끝나면 close로 닫아주어야 하고 line단위로 움직이는 객체가 있을 경우 사용후 flush로 비워주어야 하는데 new객체가 혹시 불필요하게 생성되는 구간이 없는지 확인해봐야 합니다 그리고 메모리 누수 관련은 소스 코드를 보는 것 만으로는 알 수 없으니 디버깅으로 확인해야 합니다

profile picture

익명

작성자

2024년 04월 13일

말씀해주신 부분 참고하여 디버깅 해보겠습니다. 감사합니다ㅎㅎ

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

AI 답변
커리어리 AI 봇 프로필 이미지

커리어리 AI 봇

GPT가 달아주는 답변입니다.

2024년 04월 13일

"OutOfMemoryError: GC overhead limit exceeded" 오류는 중요한 디테일을 알려 줍니다 - 가비지 컬렉터가 더 자주 호출되고 있어서 많은 시간이 그것에 소비되고 있는데도 불구하고, 얼마나 많은 메모리를 회수할 수 없다는 것을 의미합니다. 파일 크기가 8GB이므로 한 번에 읽으면 메모리 이슈가 발생합니다. 현재 전체 파일을 로드한 후 처리하는 방식 대신, Java Stream API를 사용하여 파일의 각 행(혹은 작은 일정량)을 개별적으로 처리하는 것을 고려해 보세요. 이러한 접근법은 메모리 사용량을 최소화하게 해줄 수 있습니다. 또는, PostgreSQL COPY 명령의 STDIN 옵션과 함께 pg_dump 유틸리티를 사용하여 데이터 베이스에 직접 적재하는 방법도 있습니다. 이 경우 Java 프로그램에서 데이터를 버퍼링하지 않고 직접 스트림으로 PostgreSQL로 보내므로 더 많은 메모리 절약이 가능합니다. 더 나아가서 COPY 명령의 HEADER 옵션을 사용하여 첫 번째 줄 (즉, 헤더)을 건너뛸 수도 있습니다. PostgreSQL 코드라인은 다음과 같이 보일 것입니다: ```sql COPY tableName FROM STDIN WITH (FORMAT CSV, HEADER) ``` 이렇게 하면 명시적으로 헤더를 건너뛸 수 있습니다.

목록으로

지금 가입하면 모든 질문의 답변을 볼 수 있어요!