본 내용은 조시형님의 '친절한 SQL 튜닝' 책을 읽고 이해한 내용을 바탕으로 합니다.
[목표]
- 옵티마이저가 SQL을 어떻게 처리하는지 이해할 수 있다.
- 서버 프로세스는 데이터를 어떻게 읽고 저장하는지 이해할 수 있다.
DBMS 내부에서 프로시저를 작성하고 컴파일해서 실행 가능한 상태로 만드는 전 과정.
SQL 옵티마이저는 자동차 내비게이션과 비슷하다.
경로 검색하고 이동 경로 미리 확인하는 것은 DBMS의 실행계획(Execution Plan)과 비교할 수 있다.
내비게이션이 선택한 경로가 마음에 안들면 검색모드를 변경하거나 경유지 추가해서 운전자가 원하는 경로로 바꾸는 것처럼, 개발자가 직접 힌트를 주어 실행계획을 변경할 수 있다.
또 내비게이션의 예상시각이 실제와 다를 수 있는 것처럼, cost도 예측치이기 때문에 실제와 차이가 날 수 있다.
이렇듯 SQL 옵티마이저는 (가장 효율적으로 수행 가능한) 최적의 데이터 액세스 경로를 선택해주는 DBMS의 핵심엔진이다!
=> SQL을 실행하는데, 이를 가장 빠르고 효율적으로 수행할 최적의 경로를 생성해준다.
SQL이 복잡할수록 실수할 가능성이 크다.
택시 기사님들이 경험으로 더 빠른 길을 아는 것처럼 개발자가 직접 더 효율적인 경로를 찾아낼 수도 있다. 이와 같이 개발자는 옵티마이저 힌트를 이용해서 데이터 액세스 경로를 직접 바꿀 수 있다.
이를 힌트라고 부르는데 힌트를 명시하는 방법은 다음과 같다.
/*+ (힌트명) */
/*+ INDEX(테이블 인덱스명) INDEX(테이블, 인덱스명)*/
최적화 목표
/*+ALL_LOWS */
: 전체 처리속도 최적화/*+FIRST_ROWS(N) */
: 최초 N건 응답속도 최적화액세스 방식
/*+FULL */
: 인덱스 타지말고 바로 테이블 풀스캔으로 접근해라/*+INDEX */
: 인덱스를 타라/*+INDEX_DESC */
: 인덱스를 ORDER BY DESC 역순으로 타라/*+INDEX_FFS */
: INDEX FAST FULL SCAN으로 타라/*+INDEX_SS */
: INDEX SKIP SCAN조인순서
/*+ORDERED */
: FROM절에 나열된 테이블 순서대로 조인해라/*+LEADING */
: 내가 힌트절에 열거한 테이블 순서대로 조인해라 /*+ LEADING (A B C)*/
-- A,B,C 순서대로 조인하세요/*+SWAP_JOIN_INPUTS */
: 해시조인의 경우, BUILD INPUT를 명시적으로 선택/*+ SWAP_JOIN_INPUTS(A)*/
--해시조인의경우 BUILD INPUT과 PROBE에 대한 순서를 정할 수 있다. 조인방식
/*+USE_NL */
:NL(NESTED LOOP - 중첩루프)방식 조인 유도/*+USE_MERGE */
: 소트머지 조인으로 유도/*+USE_HASH */
: 해시조인으로 유도/*+NL_SJ */
: NL SEMI조인으로 유도/*+MERGE_SJ */
: 소트머지 세미조인으로 유도/*+HASH_SJ */
: 해시 세미조인으로 유도서브쿼리팩토링
/*+MATERIALIZE */
: WITH문으로 정의한 집합을 물리적으로 생성하도록 유도 WITH /*+ MATERIALIZE*/ T AS (SELECT ...)
/*+INLINE */
: WITH문으로 정의한 집합을 물리적으로 생성하지않고 INLINE 처리하도록 유도WITH /*+ INLINE*/ T AS (SELECT ...)
쿼리변환
/*+ MEERGE */
: 뷰 머징 유도/*+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방지병렬처리
/*+PARALLEL */
: 테이블 스캔, DML 병렬방식으로 처리하도록 할때 사용.. 단일 대형 테이블의 접근시 정말 많이 쓴다./*+ PARALLEL(T1 4)*/
/*+PARALLEL_INDEX */
: 인덱스 스캔을 병렬방식으로 처리하도록 유도/*+PQ_DISTRIBUTE */
: 병렬수행시 데이터 분배방식 결정PQ_DISTRIBUTE(T1 HASH(--BUILD INPUT) HASH(--PROBE TABLE))
그외 기타
/*+APPEND*/
: DIRECT PATH INSERT유도로 INSERT 문에 주로 많이 쓴다/*+DRIVING_SITE */
: DB LINK REMOTE쿼리에 대한 최적화 및 실행 주체 지정 (LOCAL 또는 REMOTE)/*+PUSH_SUBQ */
: 서브쿼리를 가급적 빨리 필터링하도록 유도/*+NO_PUSH_SUBQ */
: 서브쿼리를 가급적 늦게 필터링 하도록 유도