안녕하세요 DBA초보입니다.
질문 사항이 있어 이렇게 글을 올리게 되었습니다.
현재 3~10만 정도 업데이트가 일어나는 배치가 있는데
아래와 같이 셀렉트를 하여 그 값을 가지고 업데이트를 합니다.
문제는 3만건 정도는 30~40분 안에 처리가 되는데,
10만건이 넘어가면 2시간이 넘어가는 이슈가 발생하여
먼가 처리를 빨리 할 수 있는 방법이 있을까.. 하여 문의를 드리게 되었습니다.
하드웨어 쪽 출신이다보니 이런 부분에 너무 약해서 혼자 고민하다가 부득불
말씀 올리게 되었습니다.
프로님들의 많은 조언 부탁 드립니다.
감사합니다.
1번) 셀렉트 하여 값을 변수로 받아옴 (자바)
select tid as "tid", rownum as "rnum" from tb_acqu
where otid = #otid:VARCHAR#
and state_cd = case when #retStateCd:VARCHAR# = '67' then '2'
when #retStateCd:VARCHAR# = '60' then '0'
else '0' end
and acqu_dt = #acquDt:VARCHAR#
and acqu_amt = #acquAmt:VARCHAR#
and acqu_rslt='1'
order by rownum desc
2번) 해당 로우가 들어간 것을 업데이트
update tb_acqu a set acqu_rslt = '2', acqu_recv_dt=#recvDt#
where a.tid = #tid:VARCHAR#
and a.state_cd = case when #retStateCd:VARCHAR# = '60' then '0'
when #retStateCd:VARCHAR# = '67' then '2' else '2' end
and a.acqu_dt = #acquDt:VARCHAR#
and a.acqu_amt = #acquAmt:VARCHAR#
"셀렉트를 하여 그 값을 가지고 업데이트를 합니다." 라고 하셨으나?
- 업데이트 문에는 셀렉트 결과를 이용하는 내용이 전혀 보이지 않고요.
-> JAVA에서 위에 셀렉트한 결과를 변수로 받아서 아래 업데이트 구문을 처리 합니다. 1번 쿼리로 셀렉트 한 결과를 같은 테이블에 2번 업데이트 구문을 이용하여 처리 합니다.
쿼리도 이상한데요.
- Select 문에 order by rownum desc 는 왜하는지?
-> 정렬을 위해서 한 것인데 빼도 무방하겠지요?
- Update 문의 조건에 acqu_rslt = '1' 조건이 없는게 맞는지?
-> 이미 1에 해당하는 조건들만 변수로 가져왔기 때문에 값은 a=1,b=2,c=3 과 같이
저장 되어 있습니다.
a1 ,... , a100 ; b1,...,b100, c1,...,c100까지 100개의 값을 변수 저장하고 있으면 업데이트를 할 때 a1,b1,c1 처리 해서 업데이트 하고 이런 식으로 100개를 일일히
업데이트를 하다 보니 그 때마다 테이블 full scan을 하는 것 같아서 성능이 너무 느려집니다... 좋은 방법이 없을까요?
일단 ,ㅠㅠ 너무 감사 드립니다. 고수께서 일일히 답변해주시기 힘드실텐데 ㅠㅠ
말씀 주신 부분은 제가 설명이 미흡했습니다.
일단 인덱스를 달고 파티션을 나누어서 셀렉트 성능은 좋아졌습니다
문제는 업데이트인데,
update tb_acqu a set acqu_rslt = '2', acqu_recv_dt=#recvDt#
where a.tid = #tid:VARCHAR#
and a.state_cd = case when #retStateCd:VARCHAR# = '60' then '0'
when #retStateCd:VARCHAR# = '67' then '2' else '2' end
and a.acqu_dt = #acquDt:VARCHAR#
and a.acqu_amt = #acquAmt:VARCHAR#
이것을 merge into로 바꾸면 성능이 향상된다고 합니다.
그게 사실인지요? 무작정 도전하기엔 시간과 다른 일들의 압박이 커서 고민하고 있습니다.
네, 저의 설명이 미흡했던 것 같습니다.
정확히는
tb_acqu라는 테이블을 정산 계열사에 보내면 정산 계열사에서 매출이 맞는지 확인하고
다시 파일로 저희 쪽에 줍니다.(개발자의 말)
파일로 준 내용을 건건히 비교 하는 것이 첫번째 select 쿼리 이고
그 내용을 비교 하여 update를 하는 것 입니다.
첫번째 쿼리가 tid만 있는 이유는 그게 유니크 하기 때문에 tid만 있으면 그 값을 가진
파일에 있는 데이터를 두번째 update 구문을 활용하여 update 시킵니다.
그래서 모두 파일에 담긴 변수 #tid:varchar# 로 기록 되어 있는 것 입니다.
저는 셀렉트는 인덱스를 주고 파티션을 나누어서 개선한다고 해도
파일에 내용을 건건히 비교하여 한 건마다 업데이트를 비교하여 치게 되는데
그러면 업데이트 대상 로우가 10만건이면 테이블을 10만번 읽을 것 같아서
이에 대한 개선점이 무엇인지 여쭈어 보는 것이 질문의 본질이었습니다.ㅠㅠ
제가 질문을 애매모호하게 하여 정말 죄송합니다.
소중한 조언을 부탁 드립니다
감사합니다.