SQLD를 준비하며 공부했던 내용으로, 2020 이기적 SQL 개발자(Developer) 이론서 + 기출문제를 참고했다.
옵티마이저 특징
옵티마이저의 필요성
옵티마이저 실행 계획 확인
DESC PLAN_TABLE;
옵티마이저의 실행 방법
규칙 기반 옵티마이저는 실행 계획을 수립할 때 15개의 우선순위를 기준으로 실행 계획을 수립함
최신 Oracle 버전은 비용 기반 옵티마이저를 기본적으로 사용
SELECT /*+ RULE */ * FROM EMP
WHERE ROWID = 'AAAHYhAABAAALNJAAN';
'/+ RULE /'를 사용해서 옵티마이저에서 규칙 기반 옵티마이저로 실행하도록 알려줌 (HINT)
'CREATE INDEX'문을 사용해서 생성 가능
인덱스를 생성할 때 한 개 이상의 칼럼을 사용해서 생성할 수 있음
인덱스 키는 기본적으로 오름차순으로 정렬하고 'DESC'구를 포함하면 내림차순으로 정렬함
CREATE INDEX IND EMP ON
EMP(ENAME ASC, SAL DESC)
Unique Index SCAN은 인덱스의 키 값이 중복되지 않는 경우, 해당 인덱스를 사용할 때 발생됨
ex.EMPNO가 중복되지 않는 경우 특정 하나의 EMPNO를 조회함
SELECT * FROM EMP WHERE EMPNO=1000;
Index Range SCAN은 SELECT문에서 특정 범위를 조회하는 WHERE문을 사용할 경우 발생함
ex. LIKE, BETWEEN / 데이터의 양이 적은 경우는 인덱스 자체를 실행하지 않고 TABLE FULL SCAN이 될 수 있음
Index Range SCAN은 인덱스의 Leaf Block의 특정 범위를 스캔한 것
SELECT EMPNO FROM EMP
WHERE EMPNO >=1000;
인덱스에서 검색되는 인덱스 키가 많은 경우에 Leaf Block의 처음부터 끝까지 전체를 읽어 들임
SELECT ENAME, SAL FROM EMP
WHERE EMPNO LIKE '%' AND SAL >0;
실행계획(Execution Plan)
EMP 테이블과 DEPT 테이블을 조인하고 EMP 테이블의 DEPTNO 번호가 10번인 것을 조회하는 SQL
SELECT * FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO
AND EMP.DEPTNO = 10;
Nested Loop방식의 조인은 DEPT 테이블에서 먼저 데이터를 찾고 그다음 EMP 테이블을 찾는 것을 의미함, 이를 Random Access라고 함
INDEX를 검색하고 ROWID를 사용해서 테이블을 조회하는 순서로 실행됨, 먼저 조회되는 테이블은 Outer Table, 그 다음 조회되는 테이블은 Inner Table
옵티마이저 조인
1) Nested Loop 조인
하나의 테이블에서 데이터를 먼저 찾고 그다음 테이블을 조인하는 방식
먼저 조회되는 테이블을 외부 테이블(Outer Table)이라고 하고 그다음 조회되는 테이블을 내부 테이블(Inner Table)이라고 함
외부 테이블(선행 테이블)의 크기가 작은 것을 먼저 찾는 것이 중요함, 데이터가 스캔되는 범위를 줄일 수 있기 때문
RANDOM ACCESS가 발생하는데 많이 발생하면 성능 지연이 발생함, RANDOM ACCESS의 양을 줄여야 성능이 향상됨
SELECT /*+ ordered use_nl(b) */ *
FROM EMP a, DEPT b
WHERE a.DEPTNO = b.DEPTNO
AND a.DEPTNO = 10;
use_nl 힌트를 사용해서 의도적으로 Nested Loop 조인을 실행함
실행 계획을 보면 EMP 테이블을 먼저 FULL SCAN하고 그다음 DEPT 테이블을 FULL SCAN하여 Nest Loop 조인을 하는 것
ordered 힌트는 FROM 절에 나오는 테이블 순서대로 조인을 하게 되는 것, ordered 힌트는 혼자 사용되지 않고 use_nl, use_merge, use_hash 힌트와 함께 조인함
2) Sort Merge 조인
두 개의 테이블을 SORT_AREA라는 메모리 공간에 모두 로딩(Loading)하고 SORT를 수행함
두 개의 테이블에 대해서 SORT가 완료되면 두 개의 테이블을 병합(Merge)함
정렬(SORT)이 발생하기 때문에 데이터양이 많아지면 성능이 떨어지게 됨
정렬 데이터양이 너무 많으면 정렬은 임시 영역에서 수행됨, 임시 영역은 디스크에 있기 때문에 성능이 급격히 떨어짐
SELECT /*+ ordered use_merge(b) */ *
FROM EMP a, DEPT b
WHERE a.DEPTNO = b.DEPTNO
AND a.DEPTNO = 10;
3) Hash 조인
두 개의 테이블 중에서 작은 테이블을 HASH 메모리에 로딩하고 두 개의 테이블의 조인 키를 사용해서 해시 테이블을 생성함
해시 함수를 사용해서 주소를 계산하고 해당 주소를 사용해서 테이블을 조인하기 때문에 CPU 연산을 많이 함
특히 Hash 조인 시에는 선행 테이블이 충분히 메모리에 로딩되는 크기여야 함
SELECT /*+ ordered use_hash(b) */ *
FROM EMP a, DEPT b
WHERE a.DEPTNO = b.DEPTNO
AND a.DEPTNO = 10;