회사에서 SYBASE를 오라클(엑사 19C)로 변경하는 작업을 진행 중 입니다.
SYBASE에서는 10 ~20분 정도 걸리는 SQL이 오라클에서는 1시간 이상이 걸립니다.
WITH T_2222 AS (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,MAX(UN_SQN) AS MX_S_NO
FROM TBL01 A --68854922
WHERE 1=1
AND UN_D_CD = '2125'
GROUP BY ANO,A_SNO
)
,T_3333 AS (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,MAX(UN_SQN) AS MX_S_NO
FROM TBL01 A --68854922
WHERE 1=1
AND UN_D_CD = '5071'
AND TT05 = 'E3'
GROUP BY ANO,A_SNO
)
SELECT
T10.ANO
, T10.A_SNO
, T10.CNO
, CASE WHEN TRIM(T11.LST_D) = '1' THEN 'Y' ELSE 'N' END
, CASE WHEN TRIM(T12.LST_D) = '1' THEN 'Y' ELSE 'N' END
, CASE WHEN TRIM(T13.LST_D) = '1' THEN 'Y' ELSE 'N' END
, TRIM(C11.CNM)
, TRIM(C12.CD_NM)
FROM (SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,CNO,ACT_DV_CD,TDT,PCD,PRD_BAL
FROM TBL10 A --186839964
) T10
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,LST_D,REG_DT,TT01,UN_D_CD
FROM TBL01 A --68854922
) T11
ON T11.ANO = T10.ANO
AND T11.A_SNO = T10.A_SNO
AND T11.UN_D_CD = '9225'
AND T11.TT01 = 'E3'
AND T11.LST_D = '1'
LEFT OUTER
JOIN T_2222 T22
ON T22.ANO = T10.ANO
AND T22.A_SNO = T10.A_SNO
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,LST_D,REG_DT,TT01,UN_D_CD
FROM TBL01 A --68854922
) T12
ON T12.ANO = T22.ANO
AND T12.A_SNO = T22.A_SNO
AND T12.UN_D_CD = T22.MX_S_NO
LEFT OUTER
JOIN T_3333 T23
ON T23.ANO = T10.ANO
AND T23.A_SNO = T10.A_SNO
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,LST_D,REG_DT,TT01,UN_D_CD
FROM TBL01 A --68854922
) T13
ON T13.ANO = T23.ANO
AND T13.A_SNO = T23.A_SNO
AND T13.UN_D_CD = T23.MX_S_NO
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
PRD_KORN_NM,PCD,PRD_APCL_ST_CD
FROM TBL02 A --41064
) C10
ON C10.PCD = T10.PCD
AND C10.PRD_APCL_ST_CD = '10'
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
CNO,CNM,TPOP_NM,STD_INDS_CLAS_NM,CORP_SCAL_CD
FROM TBL03 A --42119302
) C11
ON C11.CNO = T10.CNO
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
CD_NM,CD,UN,CD_ID
FROM TBL04 A --317780
) C12
ON C12.CD = C11.CORP_SCAL_CD
AND C12.CD_ID = '13939'
AND C12.UN = 'Y'
WHERE 1=1
AND ( TRIM(T11.ANO) IS NOT NULL OR TRIM(T12.ANO) IS NOT NULL )
------------------------------------------------------------------------------------------------
T10 테이블이 1억8천만건으로 아웃터 조인 후 마지막에 AND ( TRIM(T11.ANO) IS NOT NULL OR TRIM(T12.ANO) IS NOT NULL ) 이 조건으로 대부분의 데이터가 걸러져서 결국은
매일 1000건 이하가 조회 되어 테이블에 적재 됩니다. (1건도 없는 날도 있음)
배치 프로그램이라 특별한 힌트없이 PARALLEL만 적용을 해 보았습니다. (사실 잘 모름)
그리고 테이블명 옆의 숫자는 해당 테이블의 전체 건 수 임.
(실제 테이블명은 사정상 임의의 테이블명으로 변경을 하였습니다.)
고수 님들의 지도 부탁드립니다.
SELECT t10.ano , t10.a_sno , t10.cno , t11.yn11 , t11.yn12 , t11.yn13 , TRIM(c11.cnm) nm_11 , TRIM(c12.cd_nm) nm_12 FROM tbl10 t10 INNER JOIN (SELECT ano , a_sno , MAX(DECODE(gb, 11, 'Y', 'N')) yn11 , MAX(DECODE(gb, 12, 'Y', 'N')) yn12 , MAX(DECODE(gb, 13, 'Y', 'N')) yn13 FROM (SELECT 11 gb , ano , a_sno FROM tbl01 AND un_d_cd = '9225' AND tt01 = 'E3' AND lst_d = '1' UNION ALL SELECT a.gb , b.ano , b.a_sno FROM (SELECT DECODE(un_d_cd, '2125', 12, '5071', 13) gb , ano , a_sno , MAX(un_sqn) mx_s_no FROM tbl01 WHERE (un_d_cd = '2125') OR (un_d_cd = '5071' AND tt05 = 'E3') GROUP BY ano, a_sno, un_d_cd ) a INNER JOIN tbl01 b ON b.ano = a.ano AND b.a_sno = a.a_sno AND b.un_d_cd = a.mx_s_no AND b.lst_d = '1' ) GROUP BY ano, a_sno ) t11 ON t10.ano = t11.ano AND t10.a_sno = t11.a_sno AND 'Y' IN (t11.yn11, t11.yn12) LEFT OUTER JOIN tbl03 c11 ON c11.cno = t10.cno LEFT OUTER JOIN tbl04 c12 ON c12.cd = c11.corp_scal_cd AND c12.cd_id = '13939' AND c12.un = 'Y' ;
개발서버에 적용 후 역시나 깜짝 놀랐습니다.(겁나 빠른 속도에 음 ~~~~ 말씀하신 INDEX는 이미 존재 하여 최상의 효과를 보이는 듯 함.)
역시라는 생각을 했습니다. 사정상 전체 SQL을 올리지 못하고 일부만 줄여서 올렸었는데
SELECT 절의 추가 내용(제외 했었던 부분)을 제가 적용을 해 보려 하였으나 변경하신 내용을 모두 이해 해야 수정이 가능 할 듯 합니다. 해서 나머지 부분도 모두 올립니다.
나머지도 수정 부탁드립니다.
WITH T_2222 AS (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,MAX(UN_SQN) AS MX_S_NO
FROM TBL01 A --68854922
WHERE 1=1
AND UN_D_CD = '2125'
GROUP BY ANO,A_SNO
)
,T_3333 AS (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,MAX(UN_SQN) AS MX_S_NO
FROM TBL01 A --68854922
WHERE 1=1
AND UN_D_CD = '5071'
AND TT05 = 'E3'
GROUP BY ANO,A_SNO
)
SELECT
T10.ANO
, T10.A_SNO
, T10.CNO
, CASE WHEN TRIM(T11.LST_D) = '1' THEN 'Y' ELSE 'N' END
, CASE WHEN TRIM(T12.LST_D) = '1' THEN 'Y' ELSE 'N' END
, CASE WHEN TRIM(T13.LST_D) = '1' THEN 'Y' ELSE 'N' END
, TRIM(C11.CNM)
, TRIM(C12.CD_NM)
---------------------추가부분------------------------------------------------------------------------------------------
, CASE WHEN T11.REG_DT > CASE WHEN TRIM(T12.LST_D) = '1' THEN TRIM(T12.REG_DT) ELSE TRIM(T12.RLS_DT) END
THEN T11.REG_DT
ELSE CASE WHEN TRIM(T12.LST_D) = '1' THEN TRIM(T12.REG_DT) ELSE TRIM(T12.RLS_DT) END
END AS 상품가입일
, T11.REG_DT AS 계좌개설일
, CASE WHEN TRIM(T12.LST_D) = '1' THEN TRIM(T12.REG_DT) ELSE TRIM(T12.RLS_DT) END AS 발급일
, CASE WHEN TRIM(T13.LST_D) = '1' THEN TRIM(T13.REG_DT) ELSE TRIM(T13.RLS_DT) END AS 동의일
-----------------------------------------------------------------------------------------------------------------------
FROM (SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,CNO,ACT_DV_CD,TDT,PCD,PRD_BAL
FROM TBL10 A --186839964
) T10
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,LST_D,REG_DT,TT01,UN_D_CD
FROM TBL01 A --68854922
) T11
ON T11.ANO = T10.ANO
AND T11.A_SNO = T10.A_SNO
AND T11.UN_D_CD = '9225'
AND T11.TT01 = 'E3'
AND T11.LST_D = '1'
LEFT OUTER
JOIN T_2222 T22
ON T22.ANO = T10.ANO
AND T22.A_SNO = T10.A_SNO
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,LST_D,REG_DT,TT01,UN_D_CD
FROM TBL01 A --68854922
) T12
ON T12.ANO = T22.ANO
AND T12.A_SNO = T22.A_SNO
AND T12.UN_D_CD = T22.MX_S_NO
LEFT OUTER
JOIN T_3333 T23
ON T23.ANO = T10.ANO
AND T23.A_SNO = T10.A_SNO
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
ANO,A_SNO,LST_D,REG_DT,TT01,UN_D_CD
FROM TBL01 A --68854922
) T13
ON T13.ANO = T23.ANO
AND T13.A_SNO = T23.A_SNO
AND T13.UN_D_CD = T23.MX_S_NO
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
PRD_KORN_NM,PCD,PRD_APCL_ST_CD
FROM TBL02 A --41064
) C10
ON C10.PCD = T10.PCD
AND C10.PRD_APCL_ST_CD = '10'
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
CNO,CNM,TPOP_NM,STD_INDS_CLAS_NM,CORP_SCAL_CD
FROM TBL03 A --42119302
) C11
ON C11.CNO = T10.CNO
LEFT OUTER
JOIN (
SELECT /*+ FULL(A) PARALLEL(A 4)*/
CD_NM,CD,UN,CD_ID
FROM TBL04 A --317780
) C12
ON C12.CD = C11.CORP_SCAL_CD
AND C12.CD_ID = '13939'
AND C12.UN = 'Y'
WHERE 1=1
AND ( TRIM(T11.ANO) IS NOT NULL OR TRIM(T12.ANO) IS NOT NULL )
;
PS.혹시 유사한 내용(Sample) 또는 Reference를 추천 해 주실 수 있을까요? 한번에 이해를 하기에는 배움이 부족하네요
원하는 답을 주신 것도 황송하나 부족한 부분을 채우고 싶습니다.
SELECT t10.ano , t10.a_sno , t10.cno , t11.yn11 , t11.yn12 , t11.yn13 , TRIM(c11.cnm) nm_11 , TRIM(c12.cd_nm) nm_12 FROM tbl10 t10 INNER JOIN (SELECT ano , a_sno , MAX(CASE WHEN lst_d = '1' AND gb = 11 THEN 'Y' ELSE 'N' END) yn11 , MAX(CASE WHEN lst_d = '1' AND gb = 12 THEN 'Y' ELSE 'N' END) yn12 , MAX(CASE WHEN lst_d = '1' AND gb = 13 THEN 'Y' ELSE 'N' END) yn13 , MAX(CASE WHEN gb IN (11, 12) THEN reg_dt END) AS 상품가입일 , MAX(CASE WHEN gb = 11 THEN reg_dt END) AS 계좌개설일 , MAX(CASE WHEN gb = 12 THEN reg_dt END) AS 발급일 , MAX(CASE WHEN gb = 13 THEN reg_dt END) AS 동의일 FROM (SELECT 11 gb , ano , a_sno , lst_d , reg_dt FROM tbl01 AND un_d_cd = '9225' AND tt01 = 'E3' AND lst_d = '1' UNION ALL SELECT a.gb , b.ano , b.a_sno , b.lst_d , CASE WHEN b.lst_d WHEN '1' THEN b.reg_dt ELSE b.rls_dt END reg_dt FROM (SELECT DECODE(un_d_cd, '2125', 12, '5071', 13) gb , ano , a_sno , MAX(un_sqn) mx_s_no FROM tbl01 WHERE (un_d_cd = '2125') OR (un_d_cd = '5071' AND tt05 = 'E3') GROUP BY ano, a_sno, un_d_cd ) a INNER JOIN tbl01 b ON b.ano = a.ano AND b.a_sno = a.a_sno AND b.un_d_cd = a.mx_s_no ) GROUP BY ano, a_sno ) t11 ON t10.ano = t11.ano AND t10.a_sno = t11.a_sno AND t11.상품가입일 IS NOT NULL LEFT OUTER JOIN tbl03 c11 ON c11.cno = t10.cno LEFT OUTER JOIN tbl04 c12 ON c12.cd = c11.corp_scal_cd AND c12.cd_id = '13939' AND c12.un = 'Y' ;
개인적인 일로 어제는 로그인을 하지 못하고 이제야 접속 해 보니 또 답을 주셨습니다.
우선 감사 드리며 지난번에 달아 주신 답변과 약간 차이가 있어 질문 합니다.
AND 'Y' IN (T11.YN11, T11.YN12) 이런 부분이 있었는데 빠진 것 같은데
아마도 이부분을 AND ( TRIM(T11.ANO) IS NOT NULL OR TRIM(T12.ANO) IS NOT NULL ) ==> AND 'Y' IN (T11.YN11, T11.YN12) 이렇게 하신 것으로 예상 했는데
있어야 하지 않은가 하는 짧은 생각이 듭니다.
그리고 다시 한번 감사드립니다.