탑크리에듀(http://www.topcredu.co.kr) 제공 SQL튜닝, 오라클힌트 강좌 입니다. Subquery Factoring은 WITH구문을 이용하여 복잡한 쿼리문을 임시테이블에 저장하여 이를 이용하는 방법으로 반복되는 SELECT구문을 WITH구문에 한번만 정의하여 사용하여 쿼리 성능을 향상 시킬 수 있는 방법 입니다.
With구문은 SQL-99 표준이며 오라클에서는 9.2에 도입되었으며 복잡한 인라인뷰등을 WITH구문을 이용하여 한곳으로 몰아 가독성 또한 좋습니다.
오라클 옵티마이저는 WITH구문의 내용이 복잡할 경우 서브쿼리를 Global Temporary Table에 넣어 WITH구 블록이 여러곳에서 참조되는 경우 효율적으로 구성할 수도 있으며 Materialize 힌트는 서브쿼리 블록을 Global Temporary Table로 만들어서 사용하라는 힌트이며 Inline 힌트는 반대로 해당 WITH 쿼리블럭을 메인 쿼리블럭에 넣어 그대로 실행하라는 힌트 입니다.
본원에서는 SQL튜닝 온라인 화상강의도 무료로 진행하고 있으니홈페이지에서 확인 바랍니다. 감사합니다.
3. Subquery Factoring
• Subquery Factoring은 WITH구문을 이용하여 복잡한 쿼리문을 임시테이블에 저장하여
이를 이용하는 방법이다. 반복되는 SELECT구문을 WITH구문에 한번만 정의하여 사용하
여 쿼리 성능을 향상 시킬 수 있는 방법이다.
• With구문은 SQL-99 표준이며 오라클에서는 9.2에 도입되었다.
• 복잡한 인라인뷰등을 WITH구문을 이용하여 한곳으로 몰아 가독성 또한 좋다.
• 오라클 옵티마이저는 WITH구문의 내용이 복잡할 경우 서브쿼리를 Global Temporary
Table에 넣어 WITH구 블록이 여러곳에서 참조되는 경우 효율적으로 구성할 수도 있다.
• Materialize 힌트는 서브쿼리 블록을 Global Temporary Table로 만들어서 사용하라는
힌트이며 Inline 힌트는 반대로 해당 WITH 쿼리블럭을 메인 쿼리블럭에 넣어 그대로 실
행하라는 힌트이다.
이종철, 탑크리에듀(www.topcredu.co.kr)
4. _WITH_SUBQUERY 파라미터
• 오라클 11g 부터 사용가능한 파라미터로 WITH구문의 서브쿼리를 처리하는 방법을 지정
한다.
• OPTIMIZER : 옵티마이저가 알아서 처리(Default)
• MATERIALIZE : /*+ Materialize */ 힌트를 사용한 것과 같이 쿼리블럭을 Global Temporary Table을 만들
어서 처리한다. 쿼리블럭이 여러군데 사용되는 경우 장점이 있다.
• INLINEL : /*+ Inline */ 힌트를 사용한 것과 동일하며 쿼리블럭을 임시 테이블로 만들지 않고 라인 안에
넣어서 그대로 최적화를 진행한다.
• SQL> alter session set "_with_subquery" = materialize;
• SQL> alter session set "_with_subquery" = inline;
• SQL> alter session set "_with_subquery" = optimizer;
• SQL> show parameter withstring OPTIMIZER
[파라미터 확인 방법, SYS계정에서 실행]
SELECT A.KSPPINM "Parameter"
,B.KSPPSTVL "Session Value"
,C.KSPPSTVL "Instance Value"
FROM X$KSPPI A, X$KSPPCV B, X$KSPPSV C
WHERE A.KSPPINM LIKE '%with%'
AND A.INDX = B.INDX
AND A.INDX = C.INDX ;
이종철, 탑크리에듀(www.topcredu.co.kr)
5. Subquery Factoring 예문 - 1
-- WITH구문을 사용하지 않은 쿼리구문, 각 쿼리블럭을 별도의 뷰로 실행시켜 중첩루프 조인 한다.
-- 4.6초
SELECT e1.avgsal "Manager Average", e2.avgsal "Salesman Average", e3.avgsal "Clerk Average"
FROM (SELECT avg(sal) avgsal FROM myemp1
WHERE job = 'MANAGER') e1,
(SELECT job, avg(sal) avgsal FROM myemp1
WHERE job = 'SALESMAN') e2,
(SELECT job, avg(sal) avgsal FROM myemp1
WHERE job = 'CLERK') e3 ;
이종철, 탑크리에듀(www.topcredu.co.kr)
6. Subquery Factoring 예문 - 2
-- WITH구문을 사용한 쿼리구문, 옵티마이저가 알아서 임시테이블로 생성한다. 3초
WITH avgsal AS (SELECT job, avg(sal) avgsal
FROM myemp1 GROUP BY job)
SELECT e1.avgsal "Manager Average",
e2.avgsal "Salesman Average",
e3.avgsal "Clerk Average"
FROM avgsal e1, avgsal e2, avgsal e3
WHERE e1.job = 'MANAGER'
AND e2.job = 'SALESMAN'
AND e3.job = 'CLERK';
이종철, 탑크리에듀(www.topcredu.co.kr)
7. Subquery Factoring 예문 - 3
-- WITH구문에 Materialize 힌트를 사용(임시 테이블을 만들도록 강제), 3초
WITH avgsal AS (SELECT /*+ Materialize */
job, avg(sal) avgsal
FROM myemp1 GROUP BY job)
SELECT e1.avgsal "Manager Average",
e2.avgsal "Salesman Average",
e3.avgsal "Clerk Average"
FROM avgsal e1, avgsal e2, avgsal e3
WHERE e1.job = 'MANAGER'
AND e2.job = 'SALESMAN'
AND e3.job = 'CLERK';
이종철, 탑크리에듀(www.topcredu.co.kr)
8. Subquery Factoring 예문 - 4
-- WITH구문에 Inline 힌트를 사용하여 WITH구의 쿼리를 메인쿼리에 삽입(inline)하여 실행하도록
-- 4.6초, 머지조인을 한다.
WITH avgsal AS (SELECT /*+ Inline */
job, avg(sal) avgsal
FROM myemp1 GROUP BY job)
SELECT e1.avgsal "Manager Average",
e2.avgsal "Salesman Average",
e3.avgsal "Clerk Average"
FROM avgsal e1, avgsal e2, avgsal e3
WHERE e1.job = 'MANAGER'
AND e2.job = 'SALESMAN‘ AND e3.job = 'CLERK';
이종철, 탑크리에듀(www.topcredu.co.kr)
9. Subquery Factoring 예문 - 5
-- WITH구문에 Inline 힌트를 사용하고 USE_NL힌트를 사용하여 WITH구 블록의 뷰를 중첩루프조
인하도록 4.9초, 중첩루프조인 한다.
WITH avgsal AS (SELECT /*+ Inline */
job, avg(sal) avgsal
FROM myemp1 GROUP BY job)
SELECT /*+ use_nl(e2 e3) */
e1.avgsal "Manager Average",
e2.avgsal "Salesman Average",
e3.avgsal "Clerk Average"
FROM avgsal e1, avgsal e2, avgsal e3
WHERE e1.job = 'MANAGER'
AND e2.job = 'SALESMAN‘ AND e3.job = 'CLERK'; 이종철, 탑크리에듀(www.topcredu.co.kr)