생계/SQL2019. 6. 6. 19:05

서브쿼리란 무엇인지 개념과 활용을 알아보자 

1.  조인과의 차이 

  조인과 서브쿼리는 구조적으로 차이가 있다.

  조인은 A, B 두 집합이 동등한 관계인 반면 서브쿼리는 종속적 관계가 나타난다. 

  Select a.col1, b.col2

   from A, B

  where a.col1 = b.col1 

  조인의 결과는 조인에 성공한 만큼 나온다. 

  A 와 B 의 관계가 1: N 이면 N 만큼 결과가 나오고 1:1 이면 1 만큼 나온다. 

   조인의 한쪽은 인라인 뷰가 될수도 있다.

   이때 둘의 관계는 동일하다고 했으므로 인라인 뷰에서 A의 컬럼을 사용할수가 없다. 

  Select a.col1, b.col2

   from A, (select b.col1 from B where a.col1 = b.col)  => X

  where a.col1 = b.col1 

  

  반면 서브쿼리는 종속적 관계가 나타난다고 했다. 

  쿼리의 결과는 1 : N 관계에도 언제나 1 이다.

  종속적 관계라서 서브쿼리에 A 의 컬럼을 사용할수 있다. 

  select a.col1

    from A

   where exists (select '1' from B where a.col1 = b.col1 )

 스칼라서브쿼리도 동일한 성질을 갖는다. ( 결과row 가 변하지 않는다, 종속적 관계이다.)


# 서브쿼리 역할 : 확인 or 공급
1. 확인 : 데이터 증가 X. 감소만.
2. 공급 : 주쿼리로 공급

# 선/후 수행 서브쿼리
- 선수행 서브쿼리 : 서브쿼리 테이블이 driving, 모든 값에 엑세스. 
unique 정렬 수행. 메모리에 임시 집합 구성. 
- 후수행 서브쿼리 : driving 에서 조건에 만족하는 한건의 데이터에 대해 
    서브쿼리를 한번 수행. 만족하면 결과로 추출. 
    주 쿼리의 데이터 건수 만큼 반복 수행. 
    
# 서브쿼리 실행계획 제어

1. NL join -> Hash join

select colC, sum(colD)
 from tab a
 where colA in (select col
   from tab b
    where colB = 'X')
  and colB between '20190101' and '20191010'
 group by colC;
=>

1-1) 힌트

select /*+ USE_HASH(a,@SQ) */
colC, sum(colD)
 from tab a
 where colA in (select /*+ QB_NAME(SQ) */
   col
   from tab b
    where colB = 'X')
  and colB between '20190101' and '20191010'
 group by colC; 
 
 
1-2) 인덱스 사용 못하게
 
select colC, sum(colD)
 from tab a
 where trim(colA) in (select trim(col)
   from tab b
    where colB = 'X')
  and colB between '20190101' and '20191010'
 group by colC; 
   
1-3) from 절에 풀기
   
select /*+ ORDERED USE_HASH(A,B) */
 a.colC, sum(a.colD)
  from tab a, tab b
 where a.colA = b.col
 and b.colB = 'X'
   and a.colB between '20190101' and '20191010'
 group by a.colC; 

## 메인쿼리 : 서브쿼리 = 1:M 이면 데이터가 증가. => 인라인 뷰로 1:1 관계

select /*+ USE_HASH(A,B) */
 a.colC, sum(a.colD)
  from tab a, 
   ( select col
       from tab b
      where b.colB='X'
   group by col
   )
 where a.colA = b.col
   and a.colB between '20190101' and '20191010'
 group by a.colC; 

2. 조인 순서 변경

- QB_NAME 힌트 => 선수행 서브쿼리

select /*+ PUSH_SUBQ(@SQ) */
colC, sum(colD)
 from tab a
 where colA in (select /*+ QB_NAME(SQ) */
   col
   from tab b
    where colB = 'X')
  and colB between '20190101' and '20191010'
 group by colC; 

- 일반 조인으로 변경 

select /*+ ORDERED USE_HASH(A,B) */
 a.colC, sum(a.colD)
  from tab a, 
   ( select col
       from tab b
      where b.colB='X'
   group by col
   )
 where a.colA = b.col
   and a.colB between '20190101' and '20191010'
 group by a.colC; 

  

반응형
Posted by 돌고래트레이너