오라클 힌트 사용

이형석·2025년 4월 23일

오라클 공부

목록 보기
4/6

주요 힌트

최적화 목표

  • ALL_ROWS : 전체 처리속도 최적화
  • FIRST_ROWS(N) : 최초 N 건 응답속도 최적화

액세스 방식

  • FULL : Table Full Scan으로 유도
  • INDEX : Index Scan으로 유도
  • INDEX_DESC : Index를 역순으로 스캔하도록 유도
  • INDEX_FFS : Index Fast Full Scan으로 유도
  • INDEX_SS : Index Skip Scan으로 유도

조인 순서

  • ORDERED : FROM 절에 나열된 순서대로 조인
  • LEADING : LEADING 힌트 괄호에 기술한 순서대로 조인
    ex) LEADING(A1 A2)
  • SWAP_JOIN_INPUTS : 해시 조인 시, BUILD INPUT을 명시적으로 선택
    * Build Input : 해시 맵으로 만들 테이블
    ex) SWAP_JOIN_INPUTS(A1)

조인 방식

  • USE_NL : NL 조인으로 유도
  • USE_MERGE : 소트 머지 조인으로 유도
  • USE_HASH : 해시 조인으로 유도
  • NL_SJ : NL 세미조인으로 유도
  • MERGE_SJ : 소트 머지 세미조인으로 유도
  • HASH_SJ : 해시 세미조인으로 유도

서브쿼리 팩토링

  • MATERIALIZE : WITH 문으로 정의한 집합을 물리적으로 생성하도록 유도
    ex) WITH /*+ MATERIALIZE */ AS (SELECT ...)
  • INLINE : WITH 문으로 정의한 집합을 물리적으로 생성하지 않고 INLINE 처리하도록 유도
    ex ) 위와 같음

쿼리 변환

  • MERGE : 뷰 머징 유도 (인라인뷰 포함)
  • NO_MERGE : 뷰 머징 방지
  • UNNEST : 서브쿼리 Unnesting 유도
  • NO_UNNEST : 서브쿼리 Unnesting 방지
  • PUSH_PRED : 조인조건 Pushdown 유도
  • NO_PUSH_PRED : 조인조건 Pushdown 방지
  • USE_CONCAT : OR 또는 IN-List 조건을 OR-Expansion으로 유도
  • NO_EXPAND : OR 또는 IN-List 조건에 대한 OR-Expansion 방지

병렬 처리

  • PARELLEL : 테이블 스캔 또는 DML을 병렬방식으로 처리하도록 유도
    ex) PARALLEL(A1 2) PARALLEL(A2 2)
  • PARELLEL_INDEX : 인덱스 스캔을 병렬방식으로 처리하도록 유도
  • PQ_DISTRIBUTE : 병렬 수행 시 데이터 분배 방식 결정
    ex) PQ_DISTRIBUTE(A1 HASH HASH)

기타

  • APPEND : Direct-Path Insert 로 유도
  • DRIVING_SITE : DB Link Remote 쿼리에 대한 최적화 및 실행 주체 지정(Local 또는 Remote)
  • PUSH_SUBQ : 서브쿼리를 가급적 빨리 필터링하도록 유도
  • NO_PUSH_SUBQ : 서브쿼리를 가급적 늦게 필터링 하도록 유도

사용 예시

참고

  • 테이블 ALIAS 지정시, 반드시 힌트에도 ALIAS를 사용
  • 힌트 여러개 사용시, 공백(' ')으로 구분하여 작성
ex) /*+ INDEX(A SI_COL1) INDEX(B SI_COL2) */

인덱스

기본구조

/*+ INDEX(테이블명 인덱스명) */
  • 1번 예시
SELECT /* INDEX(A SI_고객ID) */
       고객명, 연락처, 주소
  FROM 고객 A
 WHERE 고객ID = '1234'
 -- INDEX(A SI_고객ID) : A 테이블을 SI_고객ID 인덱스를 이용해 조회

* SI : Single Index, MI : Multi Index
(인덱스명을 반드시 이걸로 지을 필요는 없음)

  • 2번 예시
SELECT /*+ INDEX(A) */
       고객명, 연락처, 주소
  FROM 고객 A
-- INDEX(A) : A 테이블을 인덱스를 이용해 조회, 어떤 인덱스를 이용할지는 옵티마이저가 결정

조인순서 + 조인방식

  • 1번 예시
SELECT /*+ ordered use_nl(B) */
       -- 생략
  FROM 사원 A
     , 고객 B
-- oredred   : FROM 절에 나열된 순서로 조인
-- use_nl(B) : B를 NL방식으로 조인
  • 2번 예시
SELECT /*+ ordred use_nl(B) use_nl(C) use_hash(D) */
       -- 생략
  FROM A, B, C, D
-- ordered     : FROM 절에 나열된 순서로 조인
-- use_nl(B)   : B를 NL방식으로 조인
-- use_nl(C)   : C를 NL방식으로 조인
-- use_hash(D) : D를 해시방식으로 조인
  • 3번 예시
SELECT /*+ leading(B,D,A,C) use_nl(D) use_nl(A) use_hash(C) */
       -- 생략
  FROM A, B, C, D
-- leading(B,D,A,C) : 괄호에 명시한 순서로 조인
-- use_nl(D) : D를 NL방식으로 조인
-- use_nl(A) : A를 NL방식으로 조인
-- use_hash(C) : C를 해시방식으로 조인
  • 4번 예시 (조인 순서만 명시)
SELECT /*+ leading(B) */
       -- 생략
  FROM A, B, C
-- leading(B) : 조인의 시작테이블만 B로 고정, 나머지 순서는 옵터마이저가 결정
  • 5번 예시 (NL 조인 방식만 명시)
SELECT /*+ use_nl(A,B,C) */
       -- 생략
  FROM A, B, C
-- use_nl(A,B,C) : 괄호의 테이블을 nl방식으로 조인, 조인순서는 옵티마이저가 결정

해시 조인

  • 1번 예시(조인 방식)
SELECT /*+ use_hash(a b) */
       -- 생략
  FROM a, b
-- a와 b를 해시방식으로 조인, Build Input은 옵티마이저가 선택(각각 조건절로 거른 후 테이블의 카디널리티가 더 작은 쪽을 선택) _282p~285p 참고
-- *Build Input: 해시맵으로 만들 테이블 _해시 조인 매커니즘 참고
  • 2번 예시(조인순서 + 조인방식)
    조인 순서와 함께 사용 시, 첫 번째 테이블을 Build Input으로 선택
/*+ ordered use_hash(b) */
FROM a, b
/*+ leading(a) use_hash(b) */
FROM a, b
  • 3번 예시(SWAP_JOIN_INPUTS 힌트)
    SWAP_JOIN_INPUTS 힌트를 사용해, Build Input을 명시적으로 선택
/*+ leading(a) use_hash(b) swap_join_inputs(b) */
FROM a, b

* 3개 이상 테이블 해시조인, Build Input 지정 방법 _291p~296p 참고

서브쿼리

  • Unnest 예시
SELECT a.학생번호, a.학생이름
  FROM 학생 a
 WHERE a.입학년도 >= 2025
   AND EXISTS (
               SELECT /*+ unnest nl_sj */
                      1
                 FROM 학생
                WHERE 학생번호 = a.학생번호
                  AND 입학년도 >= 2024
              )
-- unnest : 서브쿼리를 unnest를 통해 조인
-- nl_sj : 해당 쿼리블록이 어딘가(메인쿼리등)에서 조인될 때, 조인방법으로 nl조인을 사용
  • QB_NAME 힌트 사용 예시
    QB_NAME : 쿼리블록의 이름을 지정
SELECT /*+ leading(학생@subq) use_nl(a) */
       a.학생번호, a.학생이름
  FROM 학생 a
 WHERE a.입학년도 >= 2025
   AND EXISTS (
               SELECT /*+ qb_name(subq) unnest*/
                      1
                 FROM 학생
                WHERE 학생번호 = a.학생번호
                  AND 입학년도 >= 2024
              )
-- (학생@subq) : subq라는 쿼리블록 안의 학생테이블을 의미
-- leading : 서브쿼리를 unnest를 통해 join으로 변환했기 때문에, 조인힌트인 leading 사용가능
-- use_nl : 이 쿼리의 경우, 서브쿼리 안이 아닌 메인쿼리에서 조인방식 선택 (어디서 하든 자유)
  • Merge 예시
SELECT a.회사명
     , b.입금일자
  FROM 회사 a
     , (SELECT /*+ merge */
               입금일자
          FROM 입금
       ) b
where a.회사번호 = b.회사번호
-- 뷰를 메인쿼리와 통합(한 상태에서 옵티마이저가 최적화 수행) _4.4.1절(서브쿼리 변환이 필요한 이유), 4.4.3절(뷰와 조인) 참고

참고) 친절한 SQL 튜닝 - 조시형

profile
금융IT 개발자

0개의 댓글