본문 바로가기
데이터베이스 SELECT

APPLY절(LATERAL)을 이용한 VIEW MERGING 유도

by 홍보살 2025. 4. 4.

우선 INDEX에 대해서 간단하게 말해 보겠다.

튜닝을 위해 사이트에 방문하면 크게 2가지 형태를 보인다.

INSERT,UPDATE,DELETE 로 인한 lock과 래치경합으로 인한 대기 이슈와 

SELECT 쿼리의 잘못된 작성이슈

일반적으로 SELECT 쿼리 이슈만 생각하고 여타 비용을 포함한 모든 이슈를 무시한다면

INDEX로 7할이상의 해결이 가능해진다.

어떤 사이트에서는 15개이상의 컬럼을 정렬시키는 covered index도 종종 보기도 한다.

물론 있으믄 좋긴하지..

위에 언급한 것 처럼 오로지 select만 생각한다면....

 

하고싶은 말은 index는 만능이 아니고

무결성을 위한 제약조건으의 기능이 아니라면 최소한이다.

근래 Juristocracy라는 법률주의가 세상을 뒤흔들고 있다.

법률주의 : Rule by law(법에 의한 지배  - 절대적 법의 무한 권력)
법치주의 : Rule of law(법의 지배 - 법의 한계성과 최소성 인정)

 

세상속에서 법이 최소한이어야 하듯

DBMS에서 index는 최소한이어야 한다고 생각한다.

 

그런 의미에서 오늘은 view merging 에 대해서 얘기해보고자 한다.

(inline) view 라는 것은 하나의 테이블이 from절에 표기되는 것이 아닌

하나의 쿼리가 from 절에 놓인 경우를 말하며

merge라는 건 보통 "병합"이라는 의미인데

SQL문에서 inline view를 driving table의 조건문과 병합하여 수행하라는 의미로

해석은 정반대인 해당 inline view를 하나의 테이블처럼 별도로 연산하지 말고 풀어해치라는 의미가 된다.

 

대부분의 DBMS에서 merge, no_merge 등의 힌트를 사용할 수 있으나

현실에서 힌트는 극히 제한적으로만 허용되고

근래 조명받고 있는 postgresql 의 경우 유료(EPAS, PPAS)가 아닌 경우 힌트가 제공되지 않는다.

 

특히나 전체적으로 복잡한 쿼리이거나 inline view가 group by 절로 묶인 경우에 대부분의 옵티마이저는 no_merge로 플랜을 수행한다.

그러면 그럴때마다 index 남발을 해야할까?

아니면 우기고 우겨서 힌트를 넣어야 할까?

 

우선 아래와 같은 쿼리가 있다고 치자.

select A.col1, A.col2,  isnull(B.col3, '') col3  

  from T1 as A

  left join T2 as B

     on A.col1 = B.col1

    and A.col2 = b.col2 

   and b.col4 = 'v'

 where A.col3 = 'test'

 

A, B테이블 모두 col1, col2 를 PK로 포함한다.

A테이블의 row count는 1억개

B테이블의 row count는 5억개

A테이블에는 Col3를 기준으로 인덱스가 별도로 존재하고

B테이블에도 col4를 기준으로 인덱스가 별도로 존재한다.

마지막 Where절로 return 되는 row count는 10개이다.

 

상황에 따라 다르지만

비슷한 상황 가령 B가 단일 테이블이 아닌 group by로 집계된 inline view라 가정해도 좋다.

(그럴때는 오히려 더 명확하게 대처가 가능하다.)

중요한 위와 같은 평범한 outer join일때가 당황스럽다.

 

10건의 dataset을 얻는데 5초가 소요되었다고 가정해 보자

플랜을 살펴보니 A와 B가 각자 필터링을 진행 후에 조인을 시도한다.

A를 실행하고 10건의 dataset으로 B와 조인하면 딱봐도 빠를텐데...

inline view가 아니라고 바로 포기해야 할까?

 

발상의 전환은 언제든 가능하다.

단일 테이블을 inline view 로 변형시켜 명시적으로 옵티마이저에게 view merging을 유도할 수 있다.

반드시 힌트가 없어도 그만이다.

힌트가 없는 경우 옵티마이저는 우선순위로 view merging을 시도하지만

상황에 따라 no_merge로 진행하기도 한다.

 

select A.col1, A.col2,  isnull(B.col3, '') col3  

  from T1 as A

  OUTER APPLY -- >> 오라클도 동일하게 postgresql이라면 left join lateral 로 표현

(select col3  from  T2

                where 1 = 1

                   and A.col1 = B.col1

                   and A.col2 = b.col2

                   and col4 = 'v' ) as B

 where A.col3 = 'test'

 

참고로 위의 쿼리는 상상이므로 실전에서는 무난하게 진행될 확률이 높다.

그럼에도 머리속에서 그려지기만 하면 대응이 가능할 것으로 본다.

 

20세기 중후반 실천하는 사회학자 부르디외의 코멘트를 조금만 비틀어(원본은 검정색 괄호안 붉은색은 내 생각) 마무리 하겠다.

우리는 결정된 채로 태어났지만(인정 ㅠㅠ)
자유로운 상태(폭넓게 사유할 수 있는 상태)로 생을 마칠 수 있는
작은(타협하지 않는다면 무수히 많은) 기회를 갖고 있다.

 

이 글은 이비니어스( www.evinious.co.kr )의 소유이며 불펌은 허락하지 않습니다.

 

    개발문의는 아래 클릭 ↓