대량의 데이터 select 및 insert ㅠㅠ outofmemory 0 8 11,428

by 나도개발자다! [Oracle 에러코드] 대량 insert select [2016.03.01 09:24:36]


제가 대량의 데이터를 복사하고싶은데요

즉슨

1. 다른유저의 데이터를 select 해서 rs(resultset) 와 rsmd(resultsetmetadata)등을 통해 데이터를 읽어와

제가 접속해있는 유저로 insert를 하려고합니다.

그런데 복사까진 잘되는데

100만건의 데이터를 하고싶습니다.

1테이블에 100개의 칼럼 100자 이상 한칼럼당 10000의 데이터로 해서 100만건입니다.

addBatch(물론 이건 속도라곤 함ㅠ)부터 메모리 줄일수 있는건 다해봤는데 최대 40000만건 이상 들어가질않고

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
이게 떠버리고 마네요
메모리를 효율적으로 관리하고싶습니다. 물론 뭐 스트링을 스트링버퍼로 바꾼다고 그게 문제가 아닌것같고.
무슨 방법이 없을까욘??

by 아발란체 [2016.03.02 10:42:56]

오라클이 아닌 자바쪽 에러인가용? @.@)/

자바라면,

메모리에 무제한으로 올리는 것이 아닌 중간 중간 끊어 처리를 하거나 

java -Xmx로 최대 메모리 heap size를 늘려야 할 것 같네요.


by 나도개발자다! [2016.03.02 10:45:46]

ㅠㅠ xms 는 64 xmx는 고정 128로 힙사이즈를 올리기 보다 
안정화로 답을 찾고싶어서용 rs를 쌓아둔 캐시를 없애고싶은데 방법을 못찾겠음 ㅠ


by 아발란체 [2016.03.02 10:57:49]

자바를 말씀하시는 것이라면,

ResultSet 객체의 인스턴스 rs를 계속 사용해야 하는 것이라면 임의로 비울 수 없습니다.

아시겠지만 rs.close()를 하면 계속 쓸 수 없고.. 분할하여 인서트 하는 것이 최선일 것 같습니다.

근데.. addBatch를 쓰신다면 PreparedStatement를 쓴다는 것 같은데, rsmd도 일회성일 것 같고,

메모리는 rs가 아닌 PreparedStatement쪽 메모리 초과 아닌가용? @.@)?

PreparedStatement는 말씀하신 것처럼 너무 많이 담으면 같은 오류가 발생합니다.

중간 중간에 executeBatch()로 처리를 해줘야 합니다.


by 나도개발자다! [2016.03.02 11:16:47]

넵 5000건마다 commit 해주곤 있는데 41600건 정도 읽어왔을때 딱되면 정확히 outofmemory가 뜨네용 ㅎㅎ

님말대로 rs의 안정화 보다 pstmt 쪽 도 한번 찾아봐야겠어용 감사합니다 ㅎ


by 창조의날개 [2016.03.02 10:50:14]

1. 페이징 쿼리를 이용해서 정당량을 잘라서 저장하고 COMMIT 하는 작업을 반복하는게 좋을듯 합니다.

 

2. 글내용으로 봐서는 같은 인스턴스내에 유저만 다른 것으로 보이는데.. 그렇다면 그냥 SELECT INSERT로도 가능 할거 같네요..

 

3. DB LINK를 이용할 수 있다면 DB  LINK로 하시는게 프로그램에서 처리 하는 것보다는 빠르겠죠..

 

4. 데이터 건수를 정당히 잘라서 프로그램으로 INSERT 쿼리를 만들고 해당 쿼리를 수행면서 중간중간 COMMIT 하는 방법도 있겠네요..

 


by 나도개발자다! [2016.03.02 11:18:09]

크흡 어렵네요 ㅠㅠ 자바 쪽에서 rs 나 stmt쪽이 뻗는 기분이라 ㅠ 


by 거제도원주민 [2016.03.02 12:32:29]

1. 다른유저의 데이터를 select 해서 rs(resultset) 와 rsmd(resultsetmetadata)등을
통해 데이터를 읽어와제가 접속해있는 유저로 insert를 하려고합니다.

--> 다른유저의 데이타를 SQL로 처리가 가능하다면
insert into 나의오너.kkk
select *
from 다른사람오너.kkk
where ....
and....
즉 DB TO DB 개념으로 처리하는 프로그램으로 유도해 보시고

만약 다른사용자의 데이타를 많이 가공하여 생성(쿼리로처리 불가시)하는 데이타라고 가졍하면
TEMP성(현재접속한테이블과 유사하게 생성) 테이블을 생성하여 무작위로 INSERT처리합니다.
즉 TEMP성 테이블(현재접속한테이블과 유사하게 생성) 은 UUID 를 적용하고
addBatch()로  아무 조건없이 생성할 수있도록 처리합니다.

이후  TEMP성 테이블과 현재 접속한 테이블을 JOIN하여 일괄 처리합니다.
merge로 처리하든 ....

이후 다음에 또 처리할때는 반드시 TEMP성테이블 데이타를 삭제한후 앞의 처리방법으로 다시하면
문제가 되지 않을것입니다.

현재 처리하는 방법은 어쩔수 없이 많은 데이타를 rs()에 가져와서 처리하게 됨으로서
톰켓이나 WAS의 메모리 full이 발생하게 될것입니다.

다양한 처리방법은 있겠지만 더 좋은 솔루션은 다은 사용자에게서.....

 


by 나도개발자다! [2016.03.02 15:03:37]

감사합니다 역시나 어렵네용 ㅠ ㅎㅎ

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입