개발자
안녕하세요. 대용량의 텍스트 파일을 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 객체입니다.
커리어리 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) ``` 이렇게 하면 명시적으로 헤더를 건너뛸 수 있습니다.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!