안녕하세요. 선배님들
평소에 쿼리를 인라인뷰를 많이 작성하는데요.
1. 인라인뷰
left outer join (
셀렉트 구문~~~ 주렁주렁
) 별칭 on 조인조건
2. cte 사용 시
with 별칭1 (필요한 테이블 셀렉트~~)
, 별칭2(필요한 테이블 셀렉트2~~)
select 컬럼 from 별칭1
조인 별칭2~~~~~
원래 1번처럼 괄호안에 다시 셀렉트하여 사용하는데
이러한게 2~3개 필요하면 쿼리가 엄청 길어지더라구요 제가 짠건데도 나중에 보면 좀 보기 힘들기도하고..
책을 보니 인라인뷰를 cte문으로 빼서 쓰면 좋다고 해서 바꿔봤는데..
이렇게 하니 상단에 미리 짜놓으니 아래 셀렉트 구문에서 핵심만 파악하고 위에서 변수선언처럼 쿼리내용을 보니
좋은거같기도하고 아닌거같기도하고...
어느게 더 속도적으로 효율적인지, 유지보수하기 가독성이 좋은지.. 고민이 되서요
실행계획은 볼줄모르고... 대충 속도는 좀 비슷한거같긴한데 결과도 같구요
어느게 더 나은 방향인지 판단이 안되는데 도움좀 부탁드립니다.
감사합니다. 좋은하루되세요!
-- 어느것을 써도 실행계획은 같습니다. -- WITH 절이용 WITH V_DEPT AS ( SELECT * FROM DEPT WHERE LOC = 'DALLAS' ) SELECT /*+ gather_plan_statistics */ A.* FROM EMP A , V_DEPT B WHERE A.DEPTNO = B.DEPTNO ; ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 5 |00:00:00.01 | 12 | | | | |* 1 | HASH JOIN | | 1 | 5 | 5 |00:00:00.01 | 12 | 1517K| 1517K| 405K (0)| |* 2 | TABLE ACCESS FULL| DEPT | 1 | 1 | 1 |00:00:00.01 | 6 | | | | | 3 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 6 | | | | ---------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("A"."DEPTNO"="DEPT"."DEPTNO") 2 - filter("LOC"='DALLAS') --------------------------------------------------------------------------------------------------------------- -- INLINE VIEW 이용 SELECT /*+ gather_plan_statistics */ A.* FROM EMP A , ( SELECT * FROM DEPT WHERE LOC = 'DALLAS') B WHERE A.DEPTNO = B.DEPTNO ; ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 5 |00:00:00.01 | 12 | | | | |* 1 | HASH JOIN | | 1 | 5 | 5 |00:00:00.01 | 12 | 1517K| 1517K| 646K (0)| |* 2 | TABLE ACCESS FULL| DEPT | 1 | 1 | 1 |00:00:00.01 | 6 | | | | | 3 | TABLE ACCESS FULL| EMP | 1 | 14 | 14 |00:00:00.01 | 6 | | | | ---------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("A"."DEPTNO"="DEPT"."DEPTNO") 2 - filter("LOC"='DALLAS')
WITH 문은 두 가지 동작방식이 있습니다.
- 인라인뷰처럼 동작하기도 하고.
- 임시테이블처럼 동작하기도 합니다.
인라인뷰처럼 동작한다면? 성능상 차이가 없겠죠.
어떤 방식으로 동작되는지는 실행계획을 확인해 보세요.
다른 방식으론 임시테이블스페이스에 임시테이블을 생성하고 사용하게 됩니다.
조회하는데 테이블을 디스크에 내려쓰고 사용하니 비효율이죠.
초창기 with 는 무조건 disk 로 내려 썼는데
지금은 일부 메모리에서도 처리되는 걸로 비효율을 줄인 걸로 압니다.
그래서 with 문의 집합이
- 한번만 사용되는 쿼리라면? 인라인뷰로 동작하구요.
- 여러번 사용되는 쿼리라면? 임시테이블 생성합니다.
with 구문이 복잡하고 느린 쿼리인데 여러번 사용된다면?
- 인라인뷰로 동작하게 되면 느린 쿼리가 여러번 수행되겠지요.
- 임시테이블 생성하면 느린 쿼리 한번만 수행해서 재사용하게 됩니다.
"이게 좋다더라"라는 말만 듣고 선택하면 안됩니다.
이는 "이런 경우에는 이게 좋다더라" 에서 앞에 단서조항이 빠진 말입니다.
경우에 따라 이게 유리할 수 도 있고 저게 유리할 수도 있습니다.
가독성을 높이는 방법으로 WITH 가 사용될 수 도 있지만
지나치게 with 만 사용하면 오히려 가독성이 떨어질 수 도 있습니다.
가독성을 높이려면
- 삐뚤빼뚤 -> 들여쓰기, 줄맞춤
- 이어쓰기 -> 내려쓰기
- 대문자만/소문자만/아무렇게나 -> 대소문자 구분(명령어는 대문자, 명칭은 소문자)
- 컴마의 위치(저는 앞쪽 컴마를 선호합니다. 사람마다 선호도 차이 있음)
등등의 방법이 있습니다.
하지만 가장 좋은 방법은 쿼리 자체를 간결하게 바꾸는 것입니다.
쿼리가 복잡하고 길면 가독성이 떨어집니다.