by 만년설 [SQL Query] 최적화 튜닝 rownum 속도 [2015.06.09 21:43:40]
SELECT * FROM (SELECT RESULT_LIST.*, ROWNUM AS RNUM FROM( SELECT USERS.ORG_CODE , ORG.ORG_NM , COMT.AUTHOR_NM , COMT.AUTHOR_CODE , USERS.MEMBER_ID , USERS.MEMBER_PWD , USERS.IHIDNUM , USERS.REAL_AUTH_YN , USERS.REAL_AUTH_ORG , USERS.USE_YN , USERS.USER_ORG_YN , USERS.INFO_AGREE_YN , USERS.FIRST_NM , USERS.LAST_NM , USERS.DMST_YN , USERS.LAST_NM|| FIRST_NM AS USER_NM , USERS.ENG_FIRST_NM , USERS.ENG_LAST_NM , USERS.ENG_FIRST_NM ||ENG_LAST_NM AS ENG_USER_NM , USERS.PWD_QESTN , USERS.PWD_ANSWER , USERS.PWD_UPDT_DT , USERS.BRTH_DT , USERS.CLD_TYPE , USERS.DTY , USERS.POSTNO , USERS.BASE_ADRES , USERS.DTL_ADRES , USERS.TELNO , USERS.MOBILENO , USERS.LIVE_YN , USERS.EMAIL , USERS.EMAIL_RCV_YN , USERS.RS_MGR_YN , USERS.FRST_REGIST_PNTTM , USERS.APPRVL_YN , USERS.APPRVL_DT , USERS.USER_AMD_NO , USERS.ESNTL_ID , USERS.ATCH_FILE_ID , USERS.FRST_REGISTER_ID , USERS.LAST_UPDUSR_ID , USERS.MEM_STTUS_CODE , USERS.MEM_REGIST_SE , USERS.RWENP_YN , USERS.USR_TYPE , USERS.LAST_UPDT_PNTTM , USERS.REAL_AUTH_SE , USERS.REAL_AUTH_FAIL_REASON FROM USERS USERS INNER JOIN ORG ORG ON ORG.ORG_CODE = USERS.ORG_CODE LEFT OUTER JOIN (SELECT BB.ESNTL_ID AS ESNTL_ID , LISTAGG(AA.AUTHOR_CODE, ', ') WITHIN GROUP (ORDER BY AA.AUTHOR_CODE) AS AUTHOR_CODE, LISTAGG(AA.AUTHOR_NM, ', ' ) WITHIN GROUP (ORDER BY AA.AUTHOR_CODE) AS AUTHOR_NM FROM COMTNAUTHORINFO AA INNER JOIN COMTNEMPLYRSCRTYESTBS BB ON AA.AUTHOR_CODE = BB.AUTHOR_CODE GROUP BY BB.ESNTL_ID ) COMT ON COMT.ESNTL_ID = USERS.ESNTL_ID ORDER BY ESNTL_ID desc ) RESULT_LIST WHERE ROWNUM <= '129180') WHERE RNUM > '129160'
위에 처럼 실행하면 Execute Time : 193645ms 걸림니다 ......
SELECT * FROM (SELECT RESULT_LIST.*, ROWNUM AS RNUM FROM( SELECT USERS.ORG_CODE , ORG.ORG_NM , COMT.AUTHOR_NM , COMT.AUTHOR_CODE , USERS.MEMBER_ID , USERS.MEMBER_PWD , USERS.IHIDNUM , USERS.REAL_AUTH_YN , USERS.REAL_AUTH_ORG , USERS.USE_YN , USERS.USER_ORG_YN , USERS.INFO_AGREE_YN , USERS.FIRST_NM , USERS.LAST_NM , USERS.DMST_YN , USERS.LAST_NM|| FIRST_NM AS USER_NM , USERS.ENG_FIRST_NM , USERS.ENG_LAST_NM , USERS.ENG_FIRST_NM ||ENG_LAST_NM AS ENG_USER_NM , USERS.PWD_QESTN , USERS.PWD_ANSWER , USERS.PWD_UPDT_DT , USERS.BRTH_DT , USERS.CLD_TYPE , USERS.DTY , USERS.POSTNO , USERS.BASE_ADRES , USERS.DTL_ADRES , USERS.TELNO , USERS.MOBILENO , USERS.LIVE_YN , USERS.EMAIL , USERS.EMAIL_RCV_YN , USERS.RS_MGR_YN , USERS.FRST_REGIST_PNTTM , USERS.APPRVL_YN , USERS.APPRVL_DT , USERS.USER_AMD_NO , USERS.ESNTL_ID , USERS.ATCH_FILE_ID , USERS.FRST_REGISTER_ID , USERS.LAST_UPDUSR_ID , USERS.MEM_STTUS_CODE , USERS.MEM_REGIST_SE , USERS.RWENP_YN , USERS.USR_TYPE , USERS.LAST_UPDT_PNTTM , USERS.REAL_AUTH_SE , USERS.REAL_AUTH_FAIL_REASON FROM USERS USERS INNER JOIN ORG ORG ON ORG.ORG_CODE = USERS.ORG_CODE LEFT OUTER JOIN (SELECT BB.ESNTL_ID AS ESNTL_ID , LISTAGG(AA.AUTHOR_CODE, ', ') WITHIN GROUP (ORDER BY AA.AUTHOR_CODE) AS AUTHOR_CODE, LISTAGG(AA.AUTHOR_NM, ', ' ) WITHIN GROUP (ORDER BY AA.AUTHOR_CODE) AS AUTHOR_NM FROM COMTNAUTHORINFO AA INNER JOIN COMTNEMPLYRSCRTYESTBS BB ON AA.AUTHOR_CODE = BB.AUTHOR_CODE GROUP BY BB.ESNTL_ID ) COMT ON COMT.ESNTL_ID = USERS.ESNTL_ID ORDER BY ESNTL_ID desc ) RESULT_LIST WHERE ROWNUM <= '20') WHERE RNUM > '0'
그런데 위에 쿼리 돌리면 Execute Time : 81ms 이걸림니다.
그리고 이상한거 sqlDeveloper 로 첫번째 쿼리 돌리면 100ms 정도 밖에 안걸리던데 왜그런걸까여...
해결하려면 어떤식으로 접근해야할까요? 부탁드리겟습니다.
1. 조인 후 페이징 > 페이징 후 조인
위 쿼리에서 org 와 comt 의 역할은 단순 추가정보 조회 정도밖에 없습니다.
이러한 테이블은 일단 조인부터 하는게 아닙니다.
페이징 처리가 완전히 끝 난 뒤에 한페이지 분량만 조인하면 됩니다.
2. 조인을 스칼라 서브쿼리로
comt 의 그룹바이는 전체집합을 대상으로 합니다. 일량이 엄청나죠
이 조인을 스칼라 서브쿼리로 올려서 페이징된 20건만 처리하도록 변경하세요.
컬럼이 두개라 스칼라 2번 쓰면 총 40번 수행되겠네요.
하지만 전체를 모두 읽어 그룹바이하는것 보다는 나을 수 있습니다.
SELECT USERS.* , (SELECT LISTAGG(AA.AUTHOR_CODE, ', ') WITHIN GROUP (ORDER BY AA.AUTHOR_CODE) AS AUTHOR_CODE FROM COMTNAUTHORINFO AA INNER JOIN COMTNEMPLYRSCRTYESTBS BB ON AA.AUTHOR_CODE = BB.AUTHOR_CODE WHERE ESNTL_ID = USERS.ESNTL_ID GROUP BY BB.ESNTL_ID) AS AUTHOR_CODE, (SELECT LISTAGG(AA.AUTHOR_NM, ', ') WITHIN GROUP (ORDER BY AA.AUTHOR_CODE) AS AUTHOR_NAME FROM COMTNAUTHORINFO AA INNER JOIN COMTNEMPLYRSCRTYESTBS BB ON AA.AUTHOR_CODE = BB.AUTHOR_CODE WHERE ESNTL_ID = USERS.ESNTL_ID GROUP BY BB.ESNTL_ID) AS AUTHOR_NM FROM (SELECT RESULT_LIST.*, ROWNUM AS RNUM FROM( SELECT USERS.ORG_CODE , ORG.ORG_NM , USERS.MEMBER_ID , USERS.MEMBER_PWD , USERS.IHIDNUM , USERS.REAL_AUTH_YN , USERS.REAL_AUTH_ORG , USERS.USE_YN , USERS.USER_ORG_YN , USERS.INFO_AGREE_YN , USERS.FIRST_NM , USERS.LAST_NM , USERS.DMST_YN , USERS.LAST_NM|| FIRST_NM AS USER_NM , USERS.ENG_FIRST_NM , USERS.ENG_LAST_NM , USERS.ENG_FIRST_NM ||ENG_LAST_NM AS ENG_USER_NM , USERS.PWD_QESTN , USERS.PWD_ANSWER , USERS.PWD_UPDT_DT , USERS.BRTH_DT , USERS.CLD_TYPE , USERS.DTY , USERS.POSTNO , USERS.BASE_ADRES , USERS.DTL_ADRES , USERS.TELNO , USERS.MOBILENO , USERS.LIVE_YN , USERS.EMAIL , USERS.EMAIL_RCV_YN , USERS.RS_MGR_YN , USERS.FRST_REGIST_PNTTM , USERS.APPRVL_YN , USERS.APPRVL_DT , USERS.USER_AMD_NO , USERS.ESNTL_ID , USERS.ATCH_FILE_ID , USERS.FRST_REGISTER_ID , USERS.LAST_UPDUSR_ID , USERS.MEM_STTUS_CODE , USERS.MEM_REGIST_SE , USERS.RWENP_YN , USERS.USR_TYPE , USERS.LAST_UPDT_PNTTM , USERS.REAL_AUTH_SE , USERS.REAL_AUTH_FAIL_REASON FROM USERS USERS INNER JOIN ORG ORG ON ORG.ORG_CODE = USERS.ORG_CODE ORDER BY ESNTL_ID desc ) RESULT_LIST WHERE ROWNUM <= '20') USERS WHERE RNUM > '0'
이렇게 하니까 Execute Time : 38ms
SELECT USERS.* , (SELECT LISTAGG(AA.AUTHOR_CODE, ', ') WITHIN GROUP (ORDER BY AA.AUTHOR_CODE) AS AUTHOR_CODE FROM COMTNAUTHORINFO AA INNER JOIN COMTNEMPLYRSCRTYESTBS BB ON AA.AUTHOR_CODE = BB.AUTHOR_CODE WHERE ESNTL_ID = USERS.ESNTL_ID GROUP BY BB.ESNTL_ID) AS AUTHOR_CODE, (SELECT LISTAGG(AA.AUTHOR_NM, ', ') WITHIN GROUP (ORDER BY AA.AUTHOR_CODE) AS AUTHOR_NAME FROM COMTNAUTHORINFO AA INNER JOIN COMTNEMPLYRSCRTYESTBS BB ON AA.AUTHOR_CODE = BB.AUTHOR_CODE WHERE ESNTL_ID = USERS.ESNTL_ID GROUP BY BB.ESNTL_ID) AS AUTHOR_NM FROM (SELECT RESULT_LIST.*, ROWNUM AS RNUM FROM( SELECT USERS.ORG_CODE , ORG.ORG_NM , USERS.MEMBER_ID , USERS.MEMBER_PWD , USERS.IHIDNUM , USERS.REAL_AUTH_YN , USERS.REAL_AUTH_ORG , USERS.USE_YN , USERS.USER_ORG_YN , USERS.INFO_AGREE_YN , USERS.FIRST_NM , USERS.LAST_NM , USERS.DMST_YN , USERS.LAST_NM|| FIRST_NM AS USER_NM , USERS.ENG_FIRST_NM , USERS.ENG_LAST_NM , USERS.ENG_FIRST_NM ||ENG_LAST_NM AS ENG_USER_NM , USERS.PWD_QESTN , USERS.PWD_ANSWER , USERS.PWD_UPDT_DT , USERS.BRTH_DT , USERS.CLD_TYPE , USERS.DTY , USERS.POSTNO , USERS.BASE_ADRES , USERS.DTL_ADRES , USERS.TELNO , USERS.MOBILENO , USERS.LIVE_YN , USERS.EMAIL , USERS.EMAIL_RCV_YN , USERS.RS_MGR_YN , USERS.FRST_REGIST_PNTTM , USERS.APPRVL_YN , USERS.APPRVL_DT , USERS.USER_AMD_NO , USERS.ESNTL_ID , USERS.ATCH_FILE_ID , USERS.FRST_REGISTER_ID , USERS.LAST_UPDUSR_ID , USERS.MEM_STTUS_CODE , USERS.MEM_REGIST_SE , USERS.RWENP_YN , USERS.USR_TYPE , USERS.LAST_UPDT_PNTTM , USERS.REAL_AUTH_SE , USERS.REAL_AUTH_FAIL_REASON FROM USERS USERS INNER JOIN ORG ORG ON ORG.ORG_CODE = USERS.ORG_CODE ORDER BY ESNTL_ID desc ) RESULT_LIST WHERE ROWNUM <= '129160') USERS WHERE RNUM > '129140'
이렇게 하니까 Execute Time : 333ms 나오네요 감사합니다 ~^^