권순용의 DB 이야기
우리가 수행하는 SQL은 변한다. 2부. 1 7 99,999+

by axiom Query Transformation Transitivity 뷰 Merging View Merging 쿼리변환 [2013.01.08]


우리가 수행하는 SQL은 변한다. 이제 더 이상 우리가 수행한 SQL은 그대로 수행되지 않는다. 많은 사람들은 이를 충격으로 받아들이게 될 수도 있다. 하지만, 이러한 현상은 이제 일반적이 되었다. 이에 우리가 할 수 있는 것은 무엇일까?

SQL이 변하는 것을 막을 수 없다면 우리는 SQL이 변하는 것을 정확히 이해하고 이를 이용해야 한다. 이제부터 우리는 SQL의 변경되는 세부적인 내용을 숙지하여 이를 응용하는 능력이 필요할 것이다.

그렇다면 SQL의 실행을 주관하는 옵티마이저는 SQL을 왜 변경시키는 것일까?

그 이유는 한가지이다. SQL을 변경하여 최대한 처리 범위를 감소시킬 수 있는 조건을 확보하는 것이다.

처리 범위를 최소화시켜 성능을 향상시키고자 하는 이유가 SQL을 변경시키는 이유가 된다. 이와 같다는 것은 무엇을 의미하는가? 이를 이용한다면 우리는 최대한 처리 범위를 감소시킬 수 있다는 의미가 된다.

결국, 이와 같은 현상을 효과적으로 이용하기 위해서는 SQL의 변경에 맞는 최적의 인덱스를 생성해야지만 우리는 최대한 처리 범위를 감소시킬 수 있게 된다는 것이다.

지난 강의에 이어 이번 호에서도 SQL 변경의 핵심 요소인 Query Transformation에 대해 자세히 이야기 해보자.

Transitivity의 응용을 이해하자.

SQL이 구문 분석을 수행하는 중간에 해당 SQL을 변경하는 단계가 존재한다고 지난 강의에서 이미 언급했다. 이와 같은 단계를 Query Transformation이라고 한다. Query Transformation은 다음과 같은 단계로 구성된다.

  • - Transitivity
  • - 뷰 Merging
  • - 서브쿼리 Merging
  • - OR Expansion
  • - Query Rewrite

Transitivity는 지난 강의에 언급했듯이 WHERE 절에 존재하는 A 테이블의 상수 조건에 대해 논리적으로 타당하다면 B 테이블에도 해당 상수 조건을 옵티마이저가 추가하는 것이다.

예를 들면 아래와 같다.

SELECT 사원.사원번호, 사원.사원이름, 부서.부서번호, 부서.부서이름
  FROM 사원, 부서
 WHERE 사원.부서번호 = 부서.부서번호
   AND 부서.부서번호 = '10';

위의 SQL에서 부서,부서번호='10'인 조건과 사원.부서번호=부서.부서번호 조건에 의해 사원.부서번호='10'이라는 조건이 추가되는 것이 Transitivity 현상이다.

하지만 이와 같은 Transitivity 만을 고려하여 아래와 같이 SQL을 작성한다면 어떻게 되겠는가?

SELECT 사원.사원번호, 사원.사원이름, 부서.부서번호, 부서.부서이름 
  FROM 사원, 부서, 급여
 WHERE 사원.부서번호 = 부서.부서번호 
   AND 사원.부서번호 = 급여.부서번호;

위와 같이 SQL을 수행한다면 부서.부서번호 = 급여.부서번호는 논리적으로 당연한 사실이다. 하지만 이와 같은 조인 조건은 Transitivity가 발생하지 않게 된다.

그러므로 해당 조건이 삽입되지 않기 때문에 조인 순서 중 부서 테이블, 급여테이블 및 사원 테이블의 순서로 엑세스되는 실행 계획은 생성 되지않게 된다.

만약, 부서테이블, 급여테이블 및 사원테이블의 순서로 엑세스되는 실행 계획이 최적이라면 부서.부서번호 = 급여.부서번호 조건이 존재하지 않아 성능 저하를 발생시키는 SQL로 변하게 된다.

따라서, SQL을 작성하는 경우에 조인 조건의 설정을 매우 신중하게 설정해야 할 것이다.

뷰 Merging은 Query Transformation의 핵심이다.

뷰 Merging은 Query Transformation의 중요 요소이다. 뷰 또는 인라인 뷰를 많이 사용하게 되며 이와 같은 뷰와 인라인 뷰에서는 데이터베이스의 버전이 높아지면 높아질수록 뷰 Merging 현상은 매우 빈번히 발생하기 때문에 우리가 작성하는 SQL에서 흔하게 목격할 수 있게 된다.

이와 같은 뷰 Merging은 말 그대로 뷰가 Merging되는 것이다. 뷰 Merging에는 두 가지 종류가 존재하게 된다.

  • - 주 쿼리의 조건이 인라인 뷰 안으로 삽입되는 뷰 Merging
  • - 인라인 뷰 또는 뷰의 SQL이 주 쿼리로 합쳐지는 뷰 Merging

우선, 주 쿼리의 조건이 인라인 뷰로 삽입되는 뷰 Merging을 확인해 보자.

주 쿼리의 조건 중 인라인 뷰 또는 뷰에서 사용할 수 있는 조건이라면 해당 조건은 뷰 또는 인라인 뷰 안으로 삽입될 수 있다. 이와 같은 현상을 주 쿼리의 조건이 인라인 뷰 안으로 삽입되는 뷰 Merging이라고 한다.

예를 확인해 보자.

SELECT A.사원번호, A.사원이름, B.부서번호, B.부서이름 
  FROM 
     ( SELECT 부서번호, 사원번호, 사원이름, SUM(급여) 
         FROM 급여 
        WHERE 부서번호 = 10 
        GROUP BY 부서번호, 사원번호, 사원이름 
     ) A, 부서 B 
 WHERE A.부서번호 = B.부서번호 
   AND A.사원번호 = '100';

위와 같은 인라인 뷰를 사용한 SQL은 아래와 같이 뷰 Merging이 발생할 수 있다.

SELECT A.사원번호, A.사원이름, B.부서번호, B.부서이름 
  FROM 
     ( SELECT 부서번호, 사원번호, 사원이름, SUM(급여) 
         FROM 급여 
        WHERE 부서번호 = 10 
          AND 사원번호 = '100'
        GROUP BY 부서번호, 사원번호, 사원이름 
     ) A, 부서 B 
 WHERE A.부서번호 = B.부서번호;

뷰 Merging이 발생하면 위와 같이 주 쿼리에 존재하던 사원번호 = '100' 이라는 조건이 인라인 뷰 안으로 삽입되는 현상이 발생한다. 이와 같이 현상이 발생하여도 동일한 결과가 추출될 것이다.

이것이 바로 뷰 Merging이며 인라인 뷰는 조건을 받으므로 처리 범위를 더욱 감소시킬 수 있게 된다. 물론, 추가된 사원번호 조건이 인덱스를 이용해야만 처리 범위가 감소하게 된다.

Query Transformation 중 하나인 뷰 Merging은 매우 빈번히 발생하며 이와 같은 변화는 최대한 처리 범위를 감소시키기 위해서이다. 물론, 추출되는 결과가 변하지는 않게 된다.

이와 같이 SQL이 변경되어 처리 범위를 감소시킬 수 있는 조건을 제공받더라도 인덱스가 존재하지 않는다면 처리 범위를 감소시킬 수 없게 된다. 따라서, 뷰 Merging을 효과적으로 이용하기 위해서는 그에 맞는 최적의 인덱스가 존재해야 한다.

다음 강의에서는 뷰 Merging의 현상과 효과적인 사용에 대해 예제를 통해 확인해 보자.

- 강좌 URL : http://www.gurubee.net/lecture/2243

- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^

- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.

by 아발란체 [2013.01.09 09:01:03]
역시 개념적으로 보면 어려운 것 같아요...  >ㅅ<)ㆀ

by 참된신자 [2014.07.31 17:41:39]

감사합니다 :)


by BOREE [2019.08.06 16:48:51]

SELECT 사원.사원번호, 사원.사원이름, 부서.부서번호, 부서.부서이름

  FROM 사원, 부서, 급여

 WHERE 사원.부서번호 = 부서.부서번호

   AND 사원.부서번호 = 급여.부서번호;

만약, 부서테이블, 급여테이블 및 사원테이블의 순서로 엑세스되는 실행 계획이 최적이라면 부서.부서번호 = 급여.부서번호 조건이 존재하지 않아 성능 저하를 발생시키는 SQL로 변하게 된다. --> 이 내용을 고려해서

SELECT 사원.사원번호, 사원.사원이름, 부서.부서번호, 부서.부서이름

  FROM 사원, 부서, 급여

 WHERE 사원.부서번호 = 부서.부서번호

   AND 사원.부서번호 = 급여.부서번호;

  AND 부서.부서번호 = 급여.부서번호 ---> 이 조건을 추가하고 

AND 부서.부서번호 = '300' --> 이 조건이 존재한다면,  AND 급여.부서번호 = '300' AND 사원.부서번호 = '300'  이 추가되어 실행되는 Transivity가 발생하나요?


by JCouday [2020.04.11 15:35:04]

인라인 뷰에서 SUM(급여)를 한 이유는 뭔가요? SELECT 구문에서 쓰이지 않고 인라인뷰에서도 불필요한 거 같아서요.


by 마농 [2020.04.13 08:24:38]

네. sum(급여) 에 알리아스 부여하고 이를 메인쿼리에서 사용해야 의미가 있습니다.
다만, 여기서는 (사원번호 = '100') 조건이 어떻게 처리되는지가 중요한 부분이네요.
sum(급여) 부분은 주제(뷰머징)와 상관이 없는 내용이니 크게 신경쓰실 필요 없습니다.


by JCouday [2020.04.15 20:34:32]

확인 감사합니다 마농님!


by 비유 [2020.09.25 08:34:42]

5년이 넘는 시간동안 쿼리를 작성하면서 의아했던 부분이 이제서야 속시원히 풀리는 느낌입니다

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입