MINUS 쿼리를 튜닝하려고 하는데요 0 5 3,089

by dutch5 [Oracle Tuning] MINUS 쿼리 [2014.02.13 16:20:37]


안녕하세요
쿼리 튜닝을 하다가 좋은 방법이 떠오르지 않아서요

일단 테이블들은 100만건 이상의 레코드라고 생각하시면 됩니다.
쿼리는 해당 승인(DEAL_GB='1')만 존재하는 경우만을 출력하는 쿼리로서
승인취소((DEAL_GB='2')인  승인번호(apvl_no)를  MINUS 연산으로 제외한 경우입니다.
--------------------------------------  
 (SELECT 												
		A.APVL_YMD AS DEAL_DT,     
		A.SEUNGIN_SIGAN AS DEAL_TM,    
		CONCAT(A.APVL_YMD,A.SEUNGIN_SIGAN) AS APVL_YMDT, 
		A.APVL_NO AS APVL_NO,     
		FN_SECURE_CARDNO(A.CARD_NO) AS CARD_NO_S,  
		A.DEAL_YYMM AS DEAL_YYMM,    
		A.LOCAL_CD AS LOCAL_CD,     
		FN_LOCAL_NM(A.LOCAL_CD,'Y') AS LOCAL_NM,  
		A.BID AS BID,      
		REPLACE(B.COMP_NM,' ','') AS COMP_NM,   
		A.CAR_NO AS CAR_NO,     
		A.CAR_DIV_CD AS CAR_DIV_CD,    
		A.OIL_DIV_CD AS OIL_DIV_CD,    
		A.DEAL_TYP_CD AS DEAL_TYP_CD,    
		A.SELF_TYP_CD AS SELF_TYP_CD,    
		A.CHAIN_NM AS CHAIN_NM,     
		A.STORE_SAEOP_NO AS STORE_SAEOP_NO,   
		A.APVL_AMT AS APVL_AMT,     
		TO_CHAR(A.RITEO) AS RITEO,    
		A.SUBSIDY_MNY AS SUBSIDY_MNY,    
		A.REQ_CONFIRM_YN AS REQ_CONFIRM_YN,   
		A.DEAL_GB AS DEAL_GB,    		
		A.END_DT AS END_DT,     
		A.END_LOCAL_CD AS END_LOCAL_CD,    
		FN_LOCAL_NM(A.END_LOCAL_CD,'Y') AS END_LOCAL_NM, 
		'' AS INPUT_ID,     
		'' AS INPUT_DT,  
		'' AS UPDATE_ID,    
		'' AS UPDATE_DT  	
FROM T_BS_DEAL A      
	LEFT OUTER JOIN T_BS_BIZ_M B ON A.BID = B.BID  
	LEFT OUTER JOIN T_BS_CAR_M C ON A.BID = C.BID 				
		AND A.CAR_NO = C.CAR_NO									
WHERE A.BID = 'xxxxx'											 	
AND A.DEAL_YYMM = '201301'      
AND A.LOCAL_CD = 'xxxxx'      
	 AND A.DEAL_GB = '1'										 
)
MINUS
(       		
SELECT 												
		A.APVL_YMD AS DEAL_DT,     
		A.SEUNGIN_SIGAN AS DEAL_TM,    
		CONCAT(A.APVL_YMD,A.SEUNGIN_SIGAN) AS APVL_YMDT, 
		A.APVL_NO AS APVL_NO,     
 FN_SECURE_CARDNO(A.CARD_NO) AS CARD_NO_S,  
 A.DEAL_YYMM AS DEAL_YYMM,    
 A.LOCAL_CD AS LOCAL_CD,     
 FN_LOCAL_NM(A.LOCAL_CD,'Y') AS LOCAL_NM,  
 A.BID AS BID,      
 REPLACE(B.COMP_NM,' ','') AS COMP_NM,   
 A.CAR_NO AS CAR_NO,     
 A.CAR_DIV_CD AS CAR_DIV_CD,    
 A.OIL_DIV_CD AS OIL_DIV_CD,    
 A.DEAL_TYP_CD AS DEAL_TYP_CD,    
 A.SELF_TYP_CD AS SELF_TYP_CD,    
 A.CHAIN_NM AS CHAIN_NM,     
 A.STORE_SAEOP_NO AS STORE_SAEOP_NO,   
 A.APVL_AMT AS APVL_AMT,     
 TO_CHAR(A.RITEO) AS RITEO,    
 A.SUBSIDY_MNY AS SUBSIDY_MNY,    
 A.REQ_CONFIRM_YN AS REQ_CONFIRM_YN,   
 '1' AS DEAL_GB,      
 A.END_DT AS END_DT,     
 A.END_LOCAL_CD AS END_LOCAL_CD,    
 FN_LOCAL_NM(A.END_LOCAL_CD,'Y') AS END_LOCAL_NM, 
 '' AS INPUT_ID,      
 '' AS INPUT_DT,      
 '' AS UPDATE_ID,      
 '' AS UPDATE_DT      
FROM T_BS_DEAL A      
 LEFT OUTER JOIN T_BS_BIZ_M B ON A.BID = B.BID  
 LEFT OUTER JOIN T_BS_CAR_M C ON A.BID = C.BID   
 AND A.CAR_NO = C.CAR_NO     
WHERE A.BID = 'xxxxx'											 	
AND A.DEAL_YYMM = '201301'      
AND A.LOCAL_CD = 'xxxxx'      
 AND A.DEAL_GB = '2'
)      
 ORDER BY DEAL_DT, DEAL_TM 
결과셋이 작을 경우는 문제가 없었는데 테이블이 100만건이상이 되면서 쿼리시간이 점차 길어지는 현상이 발생하였습니다.
마이너스 연산을 대신하여  left outer 조인으로 바꾸기는 하였지만
하나의 테이블에서 조인없이 같은 결과를 낼수 있는 방법이 있을까요?

by 비니 [2014.02.13 16:27:11]

not exists 를 이용해 보심이..

by dutch5 [2014.02.13 16:31:15]
not exists도 사용해 보았는데요 Minus 연산:0.5초, Not Exists:22초가 걸립니다....
운영 DB에서는 더욱 걸리구요.... 

by 마농 [2014.02.13 16:41:57]
죄다 조인하고, 사용자 함수 쓰고, 최종결과 도출후에야 MINUS 하네요.
이렇게 하지 마시고...
기준 테이블 하나에서 키값만 가지고 MINUS 하신 결과를 이용해
다음 작업(조인 및 결과도출)을 진행하세요.

by dutch5 [2014.02.13 17:39:24]
답변 감사합니다.

지적해주신 방법대로 원 테이블에서 MINUS 연산자 처리후 조인,함수처리로 쿼리를 변경하여 센터에 테스트해보라고 요청하였습니다. 

by 마농 [2014.02.13 17:45:39]
꼭 MINUS 일 필요는 없습니다.
OUTER JOIN 이나 NOT EXISTS 또는 분석함수를 사용하셔도 되겠지요.
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입