커서를 이용한 대용량(?) INSERT 방법 문제... 0 5 9,700

by 손님 [PL/SQL] 대용량 INSERT 커서 [2011.08.11 16:10:20]


INSERT할 자료수가 3천건입니다.

먼저 태이블을 조회하여 평균치,최대치,기타 등등 횟수를 계산해서
3천 ROW의 결과물이 나오고. 이를 커서를 사용해서 다른 테이블에 INSERT 작업을 해줄계획입니다.

일단 조회된 3천건 결과물만 봐도 시간이 상당히 오래걸리는군요..1분이 넘는듯...
혹시 이런 다량의 자료를 조회하여 INSERT할 경우 어떤 방법들을 쓰고계신가요?
   
    -- 3천건 조회 쿼리
    SELECT DT,EQUIPCAT,EQUIPID,
    MAX(VAL03)MAX_VAL,
    MIN(VAL03)MIN_VAL,
    ROUND(AVG(VAL03))AVG_VAL,
    SUM(VAL03)OVR_CNT,
    SUM(CNT1) PO_CNT,
    SUM(CNT2) CO_CNT
    FROM (  SELECT TO_CHAR(T1.REGDATE,'YYYY-MM-DD HH24')DT,
    T1.EQUIPCAT,T1.EQUIPID,T1.VAL03,
    CASE WHEN T1.VAL03>0 THEN 1 ELSE 0 END CNT,
    CASE WHEN T1.VAL01=0 THEN 1 ELSE 0 END CNT1,
    CASE WHEN T1.VAL02=0 THEN 1 ELSE 0 END CNT2
    FROM HUCENS_TMP_MEASURE T1
    JOIN HUCENS_EQUIP T2
    ON T1.EQUIPCAT=T2.EQUIPCAT
    AND T1.EQUIPID=T2.EQUIPID
    AND T1.EQUIPCAT='PARK001'
    AND T1.REGDATE >= TRUNC(SYSDATE,'HH24')-1/24
    AND T1.REGDATE <  TRUNC(SYSDATE,'HH24'))
    GROUP BY DT,EQUIPCAT,EQUIPID

by 부쉬맨 [2011.08.11 16:14:38]
껀껀히 넣으신다면 늦을수밖엥없죠 통으로 일괄로 넣어야되는데
상황이 상황이라면 어쩔수없이 건건희 cursor에 선언해서 for로 insert처리하셔야겠죠
3천건이면 1분이라면 조금 손을보실필요가있을뜻합니다.
조회단에서 일단 속도가 조금 늦어보이네요 일단보기에는..

by 손님 [2011.08.11 16:15:29]
저 작업을 1시간마다 JOB을 이용해서 수행하도록 되어있습니다.

(테이블 키)
HUCENS_TMP_MEASURE
PK = REGDATE
FK = EQUIPCAT,EQUIPID

HUCENS_EQUIP
PK = EQUIPID
FK = EQUIPCAT

by 마농 [2011.08.11 17:09:00]
1. 모든 조건이 t1에만 있고 조회컬럼도 모두 t1컬럼이네요.
t2를 조인해야하는게 맞나요?
fk로 설정된걸로 봤을때 조인은 불필요합니다.

2. t1을 검색하기 위한 적절한 인덱스가 존재하나요?
(equipcat, regdate) 으로 된 인덱스가 있어야 합니다.

3. 인라인뷰 사용하지 마시고 바로 Group By 하세요.
임시 공간이 절약됩니다.

4. 기타 사소한 튜닝 팁 - else를 없애고 Count로
변경전 : SUM(CASE WHEN 조건 THEN 1 ELSE 0 END)
변경후 : COUNT(CASE WHEN 조건 THEN 1 END)
1과 0을 모두 Sum 하느냐 1만 Count 하느냐의 차이죠

5. 기타 사소한 튜닝 팁 - 불필요한 함수 사용 줄이기
변경전 : TO_CHAR(t1.regdate, 'yyyy-mm-dd hh24') dt --- 데이터 건수만큼 수행
변경후 : TO_CHAR(TRUNC(sysdate, 'hh24')-1/24, 'yyyy-mm-dd hh24') dt --- 단 한번만 수행
어차피 조회되는 dt 값은 1시간 조건으로 가져온 값이므로 모두 동일할 것입니다.

6. 기타 사소한 튜닝 팁 - 최종결과에 필요없는 항목은 과감하게 삭제
-- CASE WHEN T1.VAL03 > 0 THEN 1 ELSE 0 END CNT

마지막으로 가장 중요한것은 커서로 Loop 돌리지 마시고
Select문을 바로 Insert에 이용하세요.

INSERT INTO 대상테이블
SELECT TO_CHAR(TRUNC(sysdate, 'hh24')-1/24, 'yyyy-mm-dd hh24') dt
, t1.equipcat
, t1.equipid
, MAX(t1.val03) max_val
, MIN(t1.val03) min_val
, ROUND(AVG(t1.val03)) avg_val
, SUM(t1.val03) ovr_cnt
, COUNT(CASE WHEN t1.val01 = 0 THEN 1 END) po_cnt
, COUNT(CASE WHEN t1.val02 = 0 THEN 1 END) co_cnt
FROM hucens_tmp_measure t1
WHERE t1.equipcat = 'PARK001'
AND t1.regdate >= TRUNC(sysdate, 'hh24')-1/24
AND t1.regdate < TRUNC(sysdate, 'hh24')
GROUP BY t1.equipcat, t1.equipid
;

by 손님 [2011.08.11 17:20:48]
답변 감사합니다...팁 적용해서 수정해보겠습니다!ㅎㅎ

by 부쉬맨 [2011.08.11 19:21:34]
변경전 : TO_CHAR(t1.regdate, 'yyyy-mm-dd hh24') dt --- 데이터 건수만큼 수행
변경후 : TO_CHAR(TRUNC(sysdate, 'hh24')-1/24, 'yyyy-mm-dd hh24') dt --- 단 한번만 수행

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