3~10만건 대량 업데이트 처리 속도 개선의 문의 0 8 7,887

by 와니와플 #UPDATE [2016.08.24 11:26:42]


안녕하세요 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#   

 

by 마농 [2016.08.24 12:25:12]

"셀렉트를 하여 그 값을 가지고 업데이트를 합니다." 라고 하셨으나?
  - 업데이트 문에는 셀렉트 결과를 이용하는 내용이 전혀 보이지 않고요.
쿼리도 이상한데요.
  - Select 문에 order by rownum desc 는 왜하는지?
  - Update 문의 조건에 acqu_rslt = '1' 조건이 없는게 맞는지?
조회조건에 해당하는
  - 적절한 인덱스가 존재하는지?


by 와니와플 [2016.08.24 13:09:22]

"셀렉트를 하여 그 값을 가지고 업데이트를 합니다." 라고 하셨으나?
  - 업데이트 문에는 셀렉트 결과를 이용하는 내용이 전혀 보이지 않고요.
->
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을 하는 것 같아서 성능이 너무 느려집니다... 좋은 방법이 없을까요?


by 마농 [2016.08.24 14:01:21]

제시하신 쿼리와 설명이 일치하지 않네요.
1. Select 결과를 변수에 저장한다 했으나?
  - Select 문에서 조회하는 것은 달랑 tid 하나 뿐이고
2. 셀렉트 값을 가지고 업데이트를 한다고 했으나?
  - Update 문은 Select 문과는 전혀 연관이 없어 보이고
3. 성능이 느린 것은?
  - 적절한 인덱스가 존재하는지 확인하셔야 합니다.
결론은...똑같은 답변 또 반복이네요.


by 와니와플 [2016.08.24 15:22:56]

일단 ,ㅠㅠ 너무 감사 드립니다. 고수께서 일일히 답변해주시기 힘드실텐데 ㅠㅠ

말씀 주신 부분은 제가 설명이 미흡했습니다.

일단 인덱스를 달고 파티션을 나누어서 셀렉트 성능은 좋아졌습니다

 

문제는 업데이트인데,

 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로 바꾸면 성능이 향상된다고 합니다.

그게 사실인지요? 무작정 도전하기엔 시간과 다른 일들의 압박이 커서 고민하고 있습니다.


by 마농 [2016.08.24 15:30:50]

"뭐만 하면 빨라진다"더라?
이는 결론만 보는 것입니다.
해당 결론이 나오기 위한 전제조건이 빠진 말입니다.
"(뭐뭐뭐를 만족하는 경우에 한해서) 뭐만 하면 빨라진다" 가 정확한 표현입니다.


설명과 코드가 일치하지 않는 질문 계속 하지 마시고.
실제로 사용하는 코드를 보여 주세요.
그래야 개선점을 찾아드리죠.


by 와니와플 [2016.08.24 15:51:24]

네, 저의 설명이 미흡했던 것 같습니다.

정확히는

tb_acqu라는 테이블을 정산 계열사에 보내면 정산 계열사에서 매출이 맞는지 확인하고

다시 파일로 저희 쪽에 줍니다.(개발자의 말)

파일로 준 내용을 건건히 비교 하는 것이 첫번째 select 쿼리 이고

그 내용을 비교 하여 update를 하는 것 입니다.

첫번째 쿼리가 tid만 있는 이유는 그게 유니크 하기 때문에 tid만 있으면 그 값을 가진

파일에 있는 데이터를 두번째 update 구문을 활용하여 update 시킵니다. 

그래서 모두 파일에 담긴 변수 #tid:varchar# 로 기록 되어 있는 것 입니다.

 

저는 셀렉트는 인덱스를 주고 파티션을 나누어서 개선한다고 해도

파일에 내용을 건건히 비교하여 한 건마다 업데이트를 비교하여 치게 되는데

그러면 업데이트 대상 로우가 10만건이면 테이블을 10만번 읽을 것 같아서

이에 대한 개선점이 무엇인지 여쭈어 보는 것이 질문의 본질이었습니다.ㅠㅠ

제가 질문을 애매모호하게 하여 정말 죄송합니다.

 

소중한 조언을 부탁 드립니다

감사합니다.


by 웅 [2016.08.24 17:08:08]

updateable join view와 merge문을 연구해보시면 update를 집합으로 할 수 있습니다.


by 마농 [2016.08.24 17:09:36]

tid 가 pk 이므로 인덱스를 이용한 조회나 갱신 성능에는 문제가 없을 듯 하구요.
다만 동일 조회 및 갱신 쿼리를 10만번 반복 수행하는데 문제가 있네요.
파일을 받아서 처리하는 것이라면?
외부테이블(External Table) 기능을 이용해보면 어떨런지요?
외부테이블에 로드한뒤 MERGE 구문을 사용하면 될 듯 하네요.

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