[SQLP필기풀이]4장 조인튜닝(2)-소트머지조인&해시조인

Yu River·2022년 7월 25일
1

SQLP필기연습

목록 보기
12/35

✍️ 16번 : 소트 머지 조인 오라클 힌트

주문 테이블을 기준으로 고객 테이블과 소트 머지 조인하도록 유도하고자 할 때 빈칸에 들어갈 오라클 힌트

select /*+ ? */
o.주문번호, o.고객번호, c.고객명, c. 전화번호, o․주문금액
from 주문 o, 고객 c
where 0.주문일자 >= trunc(sysdate)
and c. 고객번호 = 0.고객번호 ; 
  1. ordered use_merge (c) 👉 ⭕️

🍋 기출 포인트

  1. 소트 머지 조인으로 유도할 때 use_merge 힌트를 사용한다.

✍️ 17번 : 소트 머지 조인 SQL Server 힌트

주문 테이블을 기준으로 고객 테이블과 소트 머지 조인하도록 유도하고자 할 때 빈칸에 들어갈 SQL Server 힌트를 기술하시오.

select o.주문번호, o.고객번호, c.고객명, c.전화번호, o.주문금액
from 주문 0, 고객 c
where 0.주문일자 >= trunc (sysdate)
and c. 고객번호 = 0. 고객번호
option ( ? )
  1. force order , merge join 👉 ⭕️

🍋 기출 포인트

  1. FROM 절에 테이블을 나열한 순으로 조인하고자 할 때 force order 힌트를 사용한다.
  2. 소트 머지 조인으로 유도할 때 merge join 힌트를 사용한다.

✍️ 18번 : 소트 머지 조인 오라클 힌트

아래 실행계획이 나타나도록 옵티마이저 힌트를 기술하시오


1. /+ leading(d) use_merge(e) / 👉 ⭕️

✍️ 19번 : 소트 머지 조인의 특징

소트 머지 조인의 특징

  1. ① 랜덤 액세스가 아닌 스캔 위주의 조인 방식이다. 👉 ⭕️
  2. ④ 두 테이블을 각각 읽어 조인 대상 집합을 줄일 수 있을 때 매우 효과적이다. 👉 ⭕️
  3. ① 양쪽 테이블 모두 조인 컬럼에 인덱스가 있으면 따로 정렬을 수행하지 않아도 되므로 매우 유리하다. 👉 ❌ (⭐️ 두번째 테이블은 무조건 따로 정렬을 수행해야함 !)
  4. ② 양쪽 집합을 개별적으로 읽어서 정렬하므로 조인 컬럼에 인덱스가 없어도 상관 없다. 👉 ⭕️

🍋 기출 포인트

  1. 소트 머지 조인이 빠른 이유는 첫 번째 집합을 기준으로 두 번째 집합을 반복 액세스할때는 버퍼캐시를 탐색하지 않고 PGA에서 데이터를 읽기 때문이다.
  2. ⭐️ 따라서 두 번째 집합은 반드시 정렬해서 PGA에 저장한 후에 조인을 시작한다.
  3. 첫 번째 집합도 일반적으로 PGA에 저장하지만, 조인 컬럼에 인덱스가 있어서 그것을 사용한다면 PGA 저장하지 않고 조인을 시작한다.

🍒 문제 해설

  1. 소트 머지 조인은 조인을 위해 실시간으로 인덱스를 생성하는 것과 다름없다.
  2. 정렬한 다음에는 NL 조인과 같은 방식으로 진행하지만, PGA 영역에 저장한 데이터를 이용하기 때문에 빠르다.
  3. 소트 부하만 감수한다면, 건건이 버퍼캐시를 경유하는 NL 조인보다 빠르다.
  4. NL 조인은 조인 컬럼에 대한 인덱스 유무에 크게 영향을 받지만, 소트 머지 조인은 영향을받지 않는다.
  5. 소트 머지 조인은 양쪽 집합을 개별적으로 읽고 나서 조인을 시작한다.조인 컬럼에 인덱스가 없는 상황에서 두 테이블을 각각 읽어 조인 대상 집합을 줄일 수 있을 때 아주 유리하다.
  6. 양쪽 소스 집합으로부터 조인 대상 레코드를 찾을 때 인덱스를 이용한다면 랜덤 액세스가 일어난다.

✍️ 20번 : 대량 데이터를 조인할 때 소트 머지 조인이 NL 조인보다 유리한 이유

대량 데이터를 조인할 때 소트 머지 조인이 NL 조인보다 유리한 이유

  1. 데이터를 PGA 영역에 읽어 들인 후 조인하기 때문이다. 👉 ⭕️
  2. Temp 테이블스페이스를 활용하기 때문이다. 👉 ❌
  3. NL 조인보다 더 빠른 조인 알고리즘을 사용하기 때문이다. 👉 ❌
  4. 조인 대상 집합을 버퍼 캐시에서 읽을 때 래치 획득을 생략하기 때문이다. 👉 ❌

🍒 문제 해설

  1. 소트 머지 조인은 Sort Area에 미리 정렬해 둔 자료구조를 이용한다는 점만 다를 뿐 조인'프로세싱 자체는 NL 조인과 같다.
  2. 대량 데이터 조인할 때 NL 조인보다 소트 머지 조인이 빠르다.
  3. 소트 머지 조인은 양쪽 테이블로부터 조인 대상 집합(조인 조건 이외 필터 조건을 만
    족하는 집합)을 ‘일괄적으로' 읽어 PGA(또는 Temp 테이블스페이스)에 저장한 후 조인한다.
  4. PGA는 프로세스만을 위한 독립적인 메모리 공간이므로 데이터를 읽을 때 래치 획득 과정이 없다.

✍️ 21번 : 소트 머지 조인의 장점

해시 조인과 비교할 때 소트 머지 조인의 장점

  1. 조인 조건이 '='이 아닐 때도 사용할 수 있다. 👉 ⭕️
  2. 양쪽 집합이 모두 대용량일 때 해시 조인보다 빠르다. 👉 ❌
  3. Temp 테이블스페이스를 적게 사용한다. 👉 ❌
  4. 메모리를 적게 사용한다. 👉 ❌

🍒 문제 해설

  1. 해시 조인과 비교한 소트 머지 조인의 가장 큰 장점은 조인 조건이 '='이 아닐 때, 심지어 조인 조건이 아예 없을 때도 사용할 수 있다는 점이다. 👉 장점
  2. 해시 조인은 둘 중 작은 쪽 집합만 읽어서 PGA에 해시 맵을 저장하는 반면, 소트 머지 조인은 양쪽 집합을 정렬해서 PGA에 저장하므로 더 많은 메모리를 사용한다. 👉 단점
  3. 상황에 따라 다르겠지만, Temp 테이블스페이스 사용량도 일반적으로 소트 머지 조인이 더 많다. 둘 중 하나만 대용량일 때 해시 조인은 Temp 테이블스페이스를 전혀 사용하지
    않는 반면, 소트 머지 조인은 Temp 테이블스페이스를 사용한다. 양쪽 집합이 모두 다용
    량일 때는 소트 머지 조인과 해시 조인 둘 다 양쪽 집합을 Temp 테이블스페이스에 저장
    한다.
    👉 단점
  4. 둘 중 어느 한쪽이 매우 작은 테이블일 때 해시 조인이 가장 극적인 성능 효과를 내는 것은 사실이지만, 둘 다 큰 테이블일 때도 일반적으로 해시 조인이 더 빠르다. 👉 단점

✍️ 22번 :해시조인 과정

() 작은 테이블을 읽는다.
() 큰 테이블을 읽는다.
() 해시 맵을 만든다.
() 해시 맵을 탐색한다.
() 조인에 성공한 데이터를 전송한다.
  1. (가) -> (다) -> (나) -> (라) -> (마) 👉 ⭕️

🍋 기출 포인트

  1. 해시 조인은 크게 두 단계로 진행한다.
    • 해시 맵 생성 (Build Phase) : 작은 테이블을 읽어서 해시 맵을 생성한다.
    • 해시 앱 탐색(Probe Phase) : 큰 테이블을 스캔하면서 해시 맵을 탐색한다.
    조인에 성공한 데이터는 클라이언트에 전송한다.

✍️ 23번 : 오라클 힌트

아래 실행계획이 나타나도록 유도하고자 할 때 빈칸에 들어갈 오라클 힌트로 가장 부적절한 것

select /*+ ? */d.deptno, d.dname, e.empno, e.ename
from emp e, dept d
where d. deptno = e.deptno ;
 이지만,  따라서 두 테이블을 조인할 때는 굳이 swap_
join_inputs 힌트를 쓰지 않고도 실행계획을 쉽게 제어할 수 있다.
①번은 
②번은 
④번과 ④번은 


1. leading(d) use_hash(e) 👉 ⭕️
1. ordered use_hash(e) 👉 ❌
1. ordered use_hash(d) swap_join_inputs(d) 👉 ⭕️
1. use_hash(e d) swap_join_inputs(d) 👉 ⭕️

🍋 기출 포인트

  1. leading(d) 힌트를 쓰면 DEPT 테이블이 Build Input으로 선택된다.
  2. ordered 힌트를 쓰면 EMP 테이블이 Build Input으로 선택된다.
  3. 3번과 4번은 swap_join_inputs 힌트에 의해 DEPT 테이블이 Build Input으로 선택된다.
  4. Build Input을 명시적으로 선택하는 힌트가 swap_join_inputs 이지만, leading 또는 ordered 힌트에 의해 선택된 첫번째 테이블은 무조건 Build Input이 된다. 따라서 두 테이블을 조인할 때는 굳이 swap_join_inputs 힌트를 쓰지 않고도 실행계획을 쉽게 제어할 수 있다.

🍒 문제 해설

  1. HASH JOIN 오퍼레이션 바로 아래쪽 테이블이 Build Input이다.
  2. 해시조인시 leading 또는 ordered 힌트에 의해 선택된 첫번째 테이블은 무조건 Build Input이 된다.
  3. Build Input을 명시적으로 선택하는 힌트는 swap_join_inputs이다.

✍️ 24번 : SQL Server 힌트

SQL Server에서 주문 테이블을 기준으로 고객 테이블과 해시 조인하도록 유도하고자 할 때 빈칸에 들어갈 용어를 적으시오.

select o.주문번호, o.고객번호, c.고객명, c. 전화번호, o, 주문금액
from 주문 o
inner ? 고객 c on ( o.고객번호 = c.고객번호 )
where 0.주문일자 >= trunc(sysdate)
option (force order)
  1. hash join 👉 ⭕️

✍️ 25번 : 해시 조인에 대한 설명

해시 조인에 대한 설명으로 가장 부적절한 것을 고르시오.

  1. 조인 컬럼에 인덱스가 없어도 성능에 미치는 영향은 없다. 👉 ⭕️
  2. 조인 조건 중 하나 이상이 '=' 조건일 때만 사용할 수 있다. 👉 ⭕️
  3. 조인하는 양쪽 집합 중 어느 한쪽이 다른 한쪽에 비해 현저히 작을 때 효과적인 조인 방식이
    다.
    👉 ⭕️
  4. 조인하는 양쪽 집합이 모두 대량 데이터일 때는 NL 조인이 유리하다. 단, 인덱스를 최적으로 구성해야 한다. 👉 ❌

🍋 기출 포인트

  1. 양쪽 모두 PGA 공간을 초과하더라도 대량 데이터를 조인할 때는 NL 조인보다 해시 조인이 빠르다.

🍒 문제 해설

  1. 해시 조인도 조인 프로세싱 자체는 NL 조인과 같지만, 건건이 Inner 집합을 버퍼캐시에서 탐색하지 않고 PGA에 미리 생성해 둔 해시 테이블(해시 맵)을 탐색하면서 조인한다는 점이 다르다. 해시 맵을 이용하므로 조인 컬럼에 인덱스가 없어도 상관 없다.
  2. 해시 맵을 PGA에 생성해야 하므로 둘 중 어느 한쪽이 PGA에 담을 수 있을 정도로 충분히 작을 때 가장 효과적이다.
  3. 해시 조인은 해시 알고리즘 특성 상 조인 조건 중 하나 이상이 '=' 조건일 때만 사용할 수 있다.

✍️ 26번 : 해시 조인과 소트 머지 조인 비교

조인하는 양쪽 집합 중 어느 한쪽이 다른 한쪽에 비해 현저히 작을 때 해시 조인이 소트 머지 조인보다 빠른 가장 핵심적인 이유

  1. 소트를 수행하지 않기 때문이다. 👉 ❌
  2. 조인 단계에 버퍼 캐시를 전혀 액세스하지 않기 때문이다. 👉 ❌
  3. 소트 알고리즘보다 해시 알고리즘이 더 빠르기 때문이다. 👉 ❌
  4. Temp 테이블스페이스를 전혀 활용하지 않을 가능성이 높기 때문이다. 👉 ⭕️

🍋 기출 포인트

  1. 해시 조인에서 사전 준비작업은 양쪽 집합 중 어느 한쪽을 읽어 해시 맵을 만드는 작업이
    다. 둘 중 작은 집합조차도 Hash Area에 담을 수 없을 정도로 큰 경우가 아니면, 해시 조인
    은 Temp 테이블스페이스, 즉 디스크에 쓰는 작업이 전혀 일어나지 않는다.
  2. 소트 머지 조인에서 사전 준비작업은 '양쪽 집합을 모두 정렬해서 PGA에 담는 작업이다.PGA는 그리 큰 메모리 공간이 아니므로 두 집합 중 어느 하나가 중대형 이상이면, Temp 테이블스페이스, 즉 디스크에 쓰는 작업을 반드시 수반한다.

🍒 문제 해설

  1. Hash Area에 생성한 해시 테이블 (해시 맵)을 이용한다는 점만 다를 뿐 해시 조인도 조인 프로세싱 자체는 NL 조인과 같다.
  2. 해시 조인이 인덱스 기반의 NL 조인보다 빠른 결정적인 이유는, 소트 머지 조인이 빠른 이유와 같다.즉, 해시 테이블을 PGA 영역에 할당하기 때문이다.
  3. 해시 조인도 Build Input과 Probe Input 각 테이블을 읽을 때는 DB 버퍼캐시를 경유한다.이때 인덱스를 이용하기도 한다.
    이 과정에서 생기는 버퍼캐시 탐색 비용과 랜덤 액세스 부하는 해시 조인이라도 피할 수 없다.
  4. 해시 조인과 소트 머지 조인 두 조인 메소드의 성능 차이는 조인 오퍼레이션을 시작하기 전, 사전 준비작업에 기인한다.

✍️ 27번 : SQL 튜닝 방안

아래 SQL에 대한 튜닝 방안으로 가장 부적절한 것을 고르시오.

[데이터]
대리점 : 1,000개
상품판매실적 : 월평균 100만 건

[인덱스 구성]
대리점_PK : 대리점코드
상품판매실적_PK : 대리점코드 + 상품코드 + 판매일자
상품판매실적 X1 : 판매일자 + 상품코드

SELECT A, 대리점명, SUM(B.매출금액) 매출금액
FROM 대리점 A, 상품판매실적 B
WHERE A.대리점코드 = B.대리점코드
AND B. 상품코드 IN ('A1847', 'Z8413' )
AND B. 판매일자 BETWEEN '20210101' AND '20210331'
GROUP BY B.대리점코드, A. 대리점명
ORDER BY 1, 2 ;

  1. 상품판매실적_X1 인덱스를 상품코드 + 판매일자」 순으로 변경한다. 👉 ⭕️
  2. 조인 순서를 변경한다. 👉 ❌
  3. 판매일자 조건을 만족하는 상품판매실적을 대리점코드로 GROUP BY 한 후 대리점 테이블과 조인하도록 SQL을 변환한다. 👉 ⭕️
  4. 해시 조인으로 유도한다. 👉 ⭕️

🍋 기출 포인트

  1. SQL을 아래와 같이 변환하면, 조인 액세스를 대리점코드별로 한 번씩만 할 수 있어 성능 개선이 된다. 단, 인라인 뷰가 Merging 되면 쿼리가 원래 형태로 돌아가므로 반드시 실행계획을 확인하고, 필요하다면 NO_MERGE 힌트로 뷰 Merging을 방지해 줘야 한다.
    SELECT A.대리점명, B. 판매금액
    FROM 대리점 A
    (SELECT /*+ NO_MERGE */ 대리점코드, SUM(판매금액) 판매금액
    FROM 상품판매실적
    WHERE 상품코드 IN ('A1847', '20413')
    AND 판매일자 BETWEEN '20210101' AND '20210331'
    GROUP BY 대리점코드) B
    WHERE A.대리점코드 = B.대리점코드 ;
  2. 해시 조인으로 유도하면 1,000 로우를 가진 대리점 테이블로 PGA에 해시맵을 만들어서
    조인하게 되므로 SGA 버퍼 캐시를 반복해서 탐색하는 비효율을 제거할 수 있다.
  3. 2021년 1~3월에 'A1847' 또는 '20413' 상품을 판매한 대리점은 30개뿐이다.
  4. 3개월 판매실적을 위해 300만 건 정도를 스캔했을 텐데 상품코드 IN 조건을 필터링한 결과는 9만 건이므로 스캔 비효율이 적지 않다.

🍒 문제 해설

  1. 상품판매실적_X1 인덱스가 판매일자 + 상품코드」 순으로 구성돼 있고, 선두 컬럼인
    판매일자가 BETWEEN 조건이므로 상품코드는 필터 조건으로 사용된다. 3개월 판매실적을
    위해 300만 건 정도를 스캔했을 텐데 상품코드 IN 조건을 필터링한 결과는 9만 건이므로
    스캔 비효율이 적지 않다. 인덱스를 상품코드 + 판매일자, 순으로 변경한다면 성능
    개선에 도움이 된다.
  2. 대리점 테이블을 먼저 읽은 후 상품판매실적과 NL 조인한다면, 1,000번의 조인 액세스가 발생한다. 2021년 1~3월에 'A1847' 또는 '20413' 상품을 판매한 대리점은 30개뿐인데, 판매가 없는 나머지 978개 대리점의 판매실적까지 읽고 버리는 비효율이 크다. 게다가,
    상품판매실적_PK 인덱스의 두 번째 컬럼인 상품코드가 IN 조건이므로 대리점별로 인덱스
    를 두 번씩 탐색하는 부담도 있다.(조인을 위해 상품판매실적_X1 인덱스를 사용한다면
    상품코드가 필터 조건이므로 인덱스를 두 번 탐색하진 않겠지만, 스캔 비효율이 매우 크
    므로 결과는 훨씬 더 안 좋을 것이다.)
  3. 현재 실행계획은 상품판매실적을 먼저 읽은 후 30개의 대리점코드에 대해 대리점 테이블을 각각 3,000번씩 반복해서 조인 액세스하고 있다.

✍️ 28번 : SQL 튜닝 방안

아래 SQL에 대한 튜닝 방안으로 가장 적절한 것을 고르시오.

[데이터]
상품 : 50rows
상품상세 : 500rows
상품변경이력 : 1,000rows

[인덱스 구성]
상품_PK : 상품코드
상품상세_PK : 상품코드 + 상품상세코드
상품상세_X1 : 등록일시 + 상품코드
상품변경이력_PK : 상품코드 + 변경일시

create table 상품상세_temp
nologging
as
select /*+ ordered use_hash(b) use_hash(c) swap_join_inputs(c) */ *
from 상품상세 a, 상품변경이력 b, 상품 c
where b.상품코드 = a.상품코드
and b. 변경일시 like substr(a. 등록일시, 1, 8) || '%'
and c.상품코드 = a. 상품코드 ;
  1. ordered use_hash(b) 힌트를 leading(b) use_hash(a)로 수정한다. 👉 ❌
  2. use_hash(b) 힌트를 use_nl(b)로 수정한다. 👉 ❌
  3. 두 번째 조건절을 아래와 같이 수정한다. 👉 ⭕️
    and substr(b. 변경일시, 1, 8) = substr(a, 등록일시, 1, 8)
  4. 힌트 전체를 leading(c a b) use_hash(a) use_hash(b) swap_join_inputs(a)로 수정한다. 👉 ❌

🍋 기출 포인트

  1. 상품코드 하나당 평균 10개의 상품상세와 평균 20개의 상품변경이력이 있으므로 어느 쪽을 해시 맵으로 선택하더라도 해시 체인 하나에 여러 레코드가 달릴 수밖에 없는 구조다.
  2. 상품상세의 등록일시를 해시 맵을 구성하는 각 해시 체인으로 값을 분배하는 기준 키 값으로 사용할 수 있으면 같은 상품이더라도 여러 체인으로 흩어진다. 그런데 조인 조건이 LIKE 이므로 해시 맵 기준 키로 사용할 수 없다.
  3. 조인 조건을 아래와 같이 '=' 조건으로 바꿔주면, a. 상품코드와 substra. 등록일시, 1, 8) 두 개의 값으로 해시 맵을 구성할 수 있게 된다.

🍒 문제 해설

  1. 해시 알고리즘 특성상 한 체인에 여러 개 값이 연결될 수 있는 구조이며, 각 해시 체인에 연결된 값이 많을수록 해시 맵 탐색 효율은 나빠진다.

    ✅ 왜 해시 조인은 조인 조건이 '='일 때만 사용할 수 있을까?

    이는 비단 해시 조인만의 특징은 아니다.
    해시 클러스터도 '=' 검색일 때만 사용할 수 있고, 해시 파티션도 '=' 검색일 때만
    Partition Pruning이 작동한다.

    [예시] 28개의 방을 가진 회사 연수원

    연수원에 입소한 신입사원들을 주민등록번호 앞 6자리를 20으로 나눈 나머지 값으로 방을 배정했다.
    이 상태에서 1998년 5월 29일에 출생한 사원이 어느 방에 있는지는 쉽게 찾을 수 있다.
    모듈러 함수가 9번 방이라고 알려주기 때문이다.
    => mod(19988529, 28) = 9
    반면, 1990년대에 출생한 사원(「주민등록번호 BETWEEN '19900101' AND '19991231′」 또는 「주민등록번호 LIKE '1996%)을 쉽게 찾는 방법은 없다.
    모든 방을 다 둘러보는 수밖에 없다.
    방금 든 예에서 20개의 방이 해시 체인에 해당하고, 방 배정에 사용한 모듈러 함수가
    해시 함수에 해당한다.
    해시 함수를 이용해 체인을 할당하고 값을 찾는 특성으로 인해 해시 조인은 조인 조건이
    '='일 때만 사용할 수 있다.
    더 정확히 표현하면, 조인 조건 중 하나 이상이 '=' 이어야 해시 조인할 수 있다.

✍️ 29번 : 해시 조인

해시 조인에 대한 설명으로 가장 부적절한 것을 고르시오

  1. 작은 집합을 해서 맵 Build Input으로 선택하는 것이 좋다. 👉 ⭕️
  2. 중복 값이 거의 없는 집합을 해서 맵 Build Input으로 선택하는 것이 좋다. 👉 ⭕️
  3. 수행 빈도가 매우 높은 쿼리는 해시 조인으로 유도하는 것이 좋다. 👉 ❌
  4. 모든 조인 조건이 '=' 이면 가장 좋고, 적어도 하나는 '=' 이어야 해시 조인할 수 있다. 👉 ⭕️

🍋 기출 포인트

  1. 해시 조인은 수행 빈도가 낮고 쿼리 수행 시간이 오래 걸리는 대량 데이터 조인할 때 사용하는 것이 좋다.
  2. 해시 맵 Build Input은 중복 값이 거의 없는 작은 집합일 때 가장 좋다.
  3. 모든 조인 조건이 '=' 조건이면 가장 좋고, 적어도 하나는 '=' 조건이어야 해시 조인이 가능하다.

✍️ 30번 : 해시 조인 사용기준

해시 조인의 사용기준으로 가장 부적절한 것을 고르시오

  1. 조인 컬럼에 적당한 인덱스가 없어 NL 조인이 비효율적일 때 사용한다. 👉 ⭕️
  2. 대량 데이터를 조인할 때 주로 사용한다. 👉 ⭕️
  3. 수행 빈도가 매우 높아 시스템 전체 성능에 미치는 영향도가 큰 쿼리에 사용한다. 👉 ❌
  4. DW/OLAP성 쿼리, BATCH 프로그램에 주로 사용한다. 👉 ⭕️

🍋 기출 포인트

  1. 수행시간이 짧으면서 수행빈도가 매우 높은 쿼리(→ OLTP성 쿼리의 특징이기도 함)를 해시 조인으로 처리하면 CPU와 메모리 사용률이 크게 증가한다.
  2. 결론적으로 해시 조인은 아래 세 가지 조건을 만족하는 SQL문에 주로 사용한다.
    ① 수행 빈도가 낮고
    ② 쿼리 수행 시간이 오래 걸리는
    ③ 대량 데이터 조인할 때
  3. 위 세 가지 조건은 배치 프로그램, DON, OLAP 쿼리의 특징이기도 하다.

🍒 문제 해설

  1. NL 조인에 사용하는 인덱스는 (DBA가 Drop하지 않는 한) 영구적으로 유지하면서 다양한 쿼리를 위해 공유 및 재사용하는 자료구조다.
  2. 해시 테이블은 단 하나의 쿼리를 위해 생성하고 조인이 끝나면 곧바로 소멸하는 자료구조다.
  3. 같은 쿼리를 100개 프로세스가 동시에 수행하면, 해시 테이블도 100개가 만들어진다.
  4. 해시 맵을 만드는 과정에 여러 가지 래치 경합도 발생한다.
  5. OLTP 환경에서도 해시 조인을 쓸 수 있지만, 이 세 가지 기준을 만족하는지 점검해 봐야 한다.

✍️ 31번 : 조인 순서에 가장 영향을 적게 받는 조인

조인 순서에 가장 영향을 적게 받는 조인 메소드를 고르시오.

  1. 소트 머지 조인 👉 ⭕️
  2. 해시 조인 👉 ❌
  3. NL 조인 👉 ❌
  4. 해시 아우터 조인 👉 ❌

🍋 기출 포인트

  1. 소트 머지 조인도 조인 순서에 따른 성능 차이가 나타나긴 하지만, NL 조인이나 해시 조인에 비하면 성능 차이가 크진 않다.

🍒 문제 해설

  1. NL 조인은 드라이빙 집합에 의해 전체 일량이 결정되므로 순서가 매우 중요하다.
  2. NL 조인은 일반적으로 작은 집합을 드라이빙하는 것이 유리하지만, 인덱스 구성에 따라서는 큰 집합을 드라이빙 하는 것이 유리할 수도 있다.
  3. 해시 조인은 Hash Area Build Input을 모두 채울 수 있느냐가 관건이므로 작은 쪽 테이블을 드라이빙하는 것이 유리하다.

✍️ 32번 : 해시조인 유도 옵티마이저 힌트

아래와 같은 실행계획이 생성되도록 옵티마이저 힌트를 기술하시오.

select a.주문번호, a․ 주문금액, b. 상품코드, c. 상품명, b. 주문수량, b. 할인률
from 주문 a, 주문상품 b, 상품 c
where b.주문번호 = a.주문번호
and c.상품코드 = b.상품코드 ; 

  1. leading(a b c) use_hash(b) use_hash(c) swap_join_inputs(c) 👉 ⭕️

🍋 기출 포인트

  1. ⭐️ 주문과 주문상품을 조인한 후에 상품과 조인하는 실행계획이다.따라서 leading 힌트의 인자는 a, b, c 순으로 나열한다.
  2. 상품(c)과 주문(a)이 Build Input이므로 각각 swap_join_inputs 힌트로 지정해 주면 된다.
  3. 주문은 leading 힌트의 첫 번째 인자로 지정했으므로 swap_join_inputs를 생략할 수 있다.
  4. leading 또는 ordered 힌트에 의해 선택된 첫 번째 테이블은 무조건 Build
    Input으로 선택된다.

🍒 문제 해설

  1. ordered(a b c)는 없다.

✍️ 33번 : 해시조인 유도 옵티마이저 힌트

아래와 같은 실행계획이 생성되도록 옵티마이저 힌트를 기술하시오.

select a. 주문번호, a. 주문금액, b. 상품코드, c. 상품명, b. 주문수량, b.할인률
from 주문 a, 주문상품 b, 상품 c
where b. 주문번호 = a. 주문번호
and c. 상품코드 = b. 상품코드 ;

  1. leading(a b c) use_hash(b) use_hash(c) no_swap_join_inputs(c) 👉 ⭕️

🍋 기출 포인트

  1. 주문과 주문상품을 조인한 집합으로 상품과 조인할 때는 상품이 Probe Input이다. Probe Input을 명시적으로 선택할 때 no_swap_join_inputs 힌트를 사용한다.

✍️ 34번 : 해시조인 유도 옵티마이저 힌트

아래와 같은 실행계획이 생성되도록 옵티마이저 힌트를 기술하시오.

select a. 주문번호, a. 주문금액, b. 상품코드, c. 상품명, b. 주문수량, b. 할인
from 주문 a, 주문상품 b. 상품 c
where b.주문번호 = a.주문번호
and c.상품코드 = b.상품코드


1. leading(c, b, a) use_hash(b) use_hash(a) swap_join_inputs(a) 👉 ⭕️

🍋 기출 포인트

  1. 상품과 주문상품을 조인한 후에 주문과 조인하는 실행계획이다. 따라서 leading 힌트의 인자는 c, b, a 순으로 나열한다.
  2. 상품(c)과 주문(a)이 Build Input이므로 각각을 swap_join_inputs 힌트로 지정해 주면 된다.
  3. 상품은 leading 힌트의 첫 번째 인자로 지정했으므로 swap_join_inputs를 생략할 수 있다.

✍️ 35번 : 해시조인 유도 옵티마이저 힌트

아래와 같은 실행계획이 생성되도록 옵티마이저 힌트를 기술하시오.

select a. 주문번호, a.주문금액, b. 상품코드, c. 상품명, b.주문수량, b.할인률
from 주문 a, 주문상품 b, 상품 c
where b.주문번호 = a․주문번호
and c.상품코드 = b.상품코드 ;

  1. leading(c b a) use_hash(b) use_hash(a) no_swap_join_inputs(a) 👉 ⭕️

✍️ 36번 : 해시조인 유도 옵티마이저 힌트

아래와 같은 실행계획이 생성되도록 옵티마이저 힌트를 기술하시오.

[인덱스 구성]
계약_PK : 계약번호
계약_X1 : 계약일자
가입상품_PK : 계약번호 + 상품번호
가입상품_X1 : 가입일자
가입부가상품_PK : 계약번호 + 상품코드 + 부가상품코드
상품_PK : 상품코드

select a.계약번호, a․계약명, b. 상품코드, b. 가입일자, b. 할인률 ,
c.부가상품코드, d. 상품명
from 계약 a, 가입상품 b, 가입부가상품 c, 상품 d
where a. 계약일자 = :cntr_dt
and b. 계약번호 = a․ 계약번호
and b. 가입일자 = :cent_dt
and c. 계약번호 = b.계약번호
and c. 상품코드 = b. 상품코드
and c. 부가상품코드 like 'A%'
and d. 상품코드 = c.부가상품코드 ;

  1. leading(b a c d) use_hash(a) use_nl(c) use_hash(d) swap_join_inputs(d) index(b 가입상품_X1) index(a 계약_x1)
    index(c 가입부가상품_PK) index(d 상품_PK)
    👉 ⭕️

✍️ 37번 : 해시조인 유도 옵티마이저 힌트

아래와 같은 실행계획이 생성되도록 옵티마이저 힌트를 기술하시오.

[ 인덱스 구성 1 ]
계약_PK : 계약번호
계약_X1 : 계약일자
가입상품_PK : 계약번호 + 상품번호
가입상품_x1 : 가입일자
가입부가상품_PK : 계약번호 + 상품코드 + 부가상품코드
상품_PK : 상품코드

select a. 계약번호, a, 계약명, b. 상품코드, b.가입일자, b. 할인률
,c.부가상품코드, d. 상품명
from 계약 a, 가입상품 b, 가입부가상품 c. 상품 d
where a.계약일자 = :cntr_dt
and b. 계약번호 = a. 계약번호
and b. 가입일자 = :cent_dt
and c. 계약번호 = b. 계약번호
and c. 상품코드 = b. 상품코드
and c.부가상품코드 like 'A%'
and d. 상품코드 = c.부가상품코드;

  1. leading(b a c d) use_hash(a) use_nl(c) use_hash(d) no_swap_join_inputs(d) index(a 계약_X1) index(b 가입상품_x1)
    index(c 가입부가상품_PK) index(d 상품_PK)
    👉 ⭕️
profile
도광양회(韜光養晦) ‘빛을 감추고 어둠속에서 힘을 기른다’

0개의 댓글