oracle 대용량 배치 쿼리 조언 부탁드립니다.. 0 6 2,907

by 꿈나무 [SQL Query] 쿼리 튜닝 거래내역 최종정보 대용량 [2024.04.22 08:55:20]


db정보: oracle 11g

배치작업 속도가 너무 오래걸려 조언 주탁드리고자

글을 올립니다.

 

INSERT INTO 일별증권원장(...)

SELECT :작업일자

     , T1.증권번호

     , T1.고객번호

     , T1.증권상태

     , NVL(T2.거래후잔액, 0)

  FROM 증권원장 T1

     , (

SELECT B.증권번호

     , B.거래일자

     , B.거래일련번호

     , B.거래후잔액

     , ROW_NUMBER() OVER(PARTITION BY B.증권번호 ORDER BY B.거래일자 DESC, B.거래일련번호 DESC) AS LAST_NUM

  FROM 증권원장 A

      , 증권거래내역  B

WHERE A.증권번호 = B.증권번호

   AND B.거래일자 <= :작업일자

   AND A.증권상태 = '1'

)  T2

 WHERE T1.증권번호 = T2.증권번호(+)

   AND T1.증권상태 = '1'

   AND T2.LAST_NUM = 1

;

 

증권원장 PK(증권번호) 1,000만건

증권거래내역 PK(증권번호, 거래일자, 거래일련번호) 5억건

[증권거래내역]테이블에서 최종정보를 가져와야하는 상황입니다..

작업일자는 어제날짜를 기준으로 하지만 소급적용하는 일이 있어 과거일자 작업을 할수도 있는 상황입니다. 그래서 [증권원장]의 최종거래정보를 신뢰할 수 없습니다..

속도가 너무 안나오는데 중간테이블을 만들거나

힌트등 좋은 방법이 있다면 추천 부탁드립니다.

감사합니다.

by 신히 [2024.04.22 13:06:42]

1,000만건을 한번에 INSERT 하신다면 REDO 생성으로 엄청 오래 걸릴 수 밖에 없습니다. 아래와 같이 성능을 올릴 수 있는 방법이 있겠네요.

1. 커서를 생성하고 1,000~10,000건씩 FETCH하여 INSERT 마다 COMMIT 처리

2. 일별증권테이블을 NOLOGGING 으로 APPEND 혹은 PARALLEL 힌트 사용


by 꿈나무 [2024.04.23 02:26:54]

답변 감사합니다. 10,000건씩 COMMIT 하면 속도 개선이 이루어질까요?? APPEND PARALLEL 힌트 사용해보겠습니다!!


by 마농 [2024.04.23 01:37:32]

증권원장이 두번 사용되네요.
한번만 사용되도록 개선 가능합니다.


by 꿈나무 [2024.04.23 02:27:44]

증권원장을 한번만 읽는 방법을 알려주시면 감사하겠습니다!!


by 마농 [2024.04.23 09:02:56]

원본 쿼리 조건에 문제가 있네요.
거래가 1건도 없는 원장의 경우에도 0 으로 입력이 되어야 한다면?
다음과 같이 바꿔야 합니다.
- 오류 : AND T2.LAST_NUM = 1
- 수정 : AND T2.LAST_NUM(+) = 1
만약, 거래가 1건도 없는 원장은 없다거나,
1건도 없는 원장은 입력될 필요가 없다면?
아우터 조인을 이너조인으로 바꿔줘야 합니다.
현재 쿼리가 맞다면? 이너조인으로 바꿔줘야 하고
현재 쿼리가 틀리다면? 아우터조인을 정확하게 적용시켜 줘야 합니다.

일단 아우터 조인을 적용해야 한다고 가정하고.
다음과 같이 2가지 방안이 있을 것 같습니다.
 

-- 1. 
SELECT :작업일자
     , T2.증권번호
     , T2.고객번호
     , T2.증권상태
     , NVL(T2.거래후잔액, 0)
  FROM (SELECT A.증권번호
             , A.고객번호
             , A.증권상태
             , B.거래후잔액
             , ROW_NUMBER() OVER(PARTITION BY A.증권번호 ORDER BY B.거래일자 DESC, B.거래일련번호 DESC) LAST_NUM
          FROM 증권원장 A
             , 증권거래내역 B
         WHERE B.증권번호(+) = A.증권번호
           AND B.거래일자(+) <= :작업일자
           AND A.증권상태 = '1'
        ) T2
 WHERE T2.LAST_NUM = 1
;

-- 2.
SELECT :작업일자
     , T1.증권번호
     , T1.고객번호
     , T1.증권상태
     , NVL(T2.거래후잔액, 0)
  FROM 증권원장 T1
     , (SELECT B.증권번호
             , B.거래후잔액
             , ROW_NUMBER() OVER(PARTITION BY B.증권번호 ORDER BY B.거래일자 DESC, B.거래일련번호 DESC) LAST_NUM
          FROM 증권거래내역 B
         WHERE B.거래일자 <= :작업일자
        ) T2
 WHERE T1.증권번호 = T2.증권번호(+)
   AND T1.증권상태 = '1'
   AND T2.LAST_NUM(+) = 1
;

 


by 꿈나무 [2024.04.24 12:01:48]

조언주신 부분으로 쿼리를 바꿔서 해결했습니다 감사합니다!!

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