D컬럼의 순서가 안맞아서 order by D를 해서 pl/sql를 써서 다른 테이블에 A,B,C컬럼이 일치하면 update 그렇지 않으면 insert를 합니다.
이게 건수가 약 1,000만건 이나 되고 order by를 줘서 업데이트 시간이 너무 오래 걸리거나 무한루프가 돌아서 잘 안되네요.
updqte 시간이 덜 걸리는 방법이 없을까요?
A B C D
A 01 1 1
B 01 1 3
A 01 1 2
B 01 1 5
C 02 2 4
B 01 1 7
C 02 2 9
B 01 1 6
A 01 1 10
C 02 2 8
----------------------------------------------------
결과값
A B C min(D) max(D)
A 01 1 1 2
B 01 2 3 3
C 02 2 4 4
B 01 1 5 7
C 02 2 8 9
A 01 1 10 10
결과값 테이블에 업데이트 한다는게 이상한데요?
min(d) 와 max(d) 를 업데이트 해야 할텐데요?
그럴려면 키를 a, b, c 를 사용하면?
중복이 되어서 안되고
a, b, c, min(d) 와 max(d) 까지를 키로 하면?
업데이트 한다는게 말이 안되구요. 키 이외에 업데이트할 컬럼이 없음.
이건 업데이트가 아니라
테이블 truncate 하고 새로 insert 하거나
테이블 drop 하고 CTAS 로 새로 만들어야 할 것 같네요. --> 성능상 ctas 추천
만약 데이터 수정은 없이 insert 만 이루어지며
주기적으로 결과테이블에 업데이트 하는 거라면?
지난번 업데이트 처리한 d 값 이후의 자료만 가지고 업데이트 하는게 좋을 듯 하네요.
전체 천만건을 대상으로 를 하는 것보다 최근 것만 가지고 하는게 성능상 좋죠.
업데이트 키는 a, b, c, MIN(d) 로 해서 update 또는 insert 하는 merge 구문 이용하면 좋을 듯.
/* 다른테이블에 전부 넣으시고 테이블 RENAME 하심이 어떠실지 ./*/ WITH T ( A , B , C , D ) AS ( SELECT 'A', '01' , 1 , 1 FROM DUAL UNION ALL SELECT 'B', '01' , 1 , 3 FROM DUAL UNION ALL SELECT 'A', '01' , 1 , 2 FROM DUAL UNION ALL SELECT 'B', '01' , 1 , 5 FROM DUAL UNION ALL SELECT 'C', '02' , 2 , 4 FROM DUAL UNION ALL SELECT 'B', '01' , 1 , 7 FROM DUAL UNION ALL SELECT 'C', '02' , 2 , 9 FROM DUAL UNION ALL SELECT 'B', '01' , 1 , 6 FROM DUAL UNION ALL SELECT 'A', '01' , 1 , 10 FROM DUAL UNION ALL SELECT 'C', '02' , 2 , 8 FROM DUAL ) INSERT INTO TABLE SELECT A , B , C , MIN(D) , MAX(D) FROM (SELECT A , B, C , D ,(ROW_NUMBER() OVER(PARTITION BY A , B , C ORDER BY D ) - D) GB FROM T ) GROUP BY A , B , C , GB ORDER BY TO_NUMBER(MIN(D))
MERGE INTO target_t a USING ( SELECT a, b, c , MIN(d) min_d , MAX(d) max_d FROM (SELECT a, b, c, d , ROW_NUMBER() OVER(ORDER BY d) - ROW_NUMBER() OVER(PARTITION BY a, b, c ORDER BY d) grp FROM source_t WHERE d >= (SELECT MAX(min_d) FROM target_t) -- 마지막 작업 이후부터 집계 ) GROUP BY a, b, c, grp -- ORDER BY d1 ) b ON (a.a = b.a AND a.b = b.b AND a.c = b.c AND a.min_d = b.min_d ) WHEN MATCHED THEN UPDATE SET a.max_d = b.max_d WHEN NOT MATCHED THEN INSERT VALUES (b.a, b.b, b.c, b.min_d, b.max_d) ;