옵티마이저(Optimizer)
- SQL의 실행 계획을 수립하고 SQL을 실행하는 DBMS의 소프트웨어
- 데이터 딕셔너리에 있는 오브젝트 통계, 시스템 통계 등의 정보를 사용하여 예상되는 비용을 산정
- 여러 실행 계획 중 최저비용을 가지는 계획을 선택하여 SQL 실행
- SQL 실행 계획을 PLAN_TABLE에 저장
- PLAN_TABLE을 조회하여 실행 계획 확인 가능
TABLE ACCESS FULL: 테이블의 전체를 모두 읽었다는 의미
옵티마이저 엔진
옵티마이저 | 설명 |
---|---|
Query Transformer | - SQL문을 효율적으로 실행하기 위해 옵티마이저가 변환 - SQL이 변환되어도 결과는 동일 |
Estimator | - 통계정보를 사용하여 SQL 실행비용 계산 - 총 비용은 최적의 실행 계획을 수립하기 위함 |
Plan Generator | SQL을 실행할 실행 계획 수립 |
규칙 기반 옵티마이저(Rule base Optimizer)
실행 계획을 수립할 때 15개의 우선순위를 기준으로 실행 계획 수립
- ROWID를 사용한 단일 행인 경우
- 클러스터 조인에 의한 단일 행인 경우
- 유일하거나 기본키를 가진 해시 클러스터 키에 의한 단일 행인 경우
- 유일하거나 기본키에 의한 단일 행인 경우
- 클러스터 조인인 경우
- 해시 클러스터 조인인 경우
- 인덱스 클러스터 키인 경우
- 복합 칼럼 인덱스인 경우
- 단일 칼럼 인덱스인 경우
- 인덱스가 구성된 칼럼에서 제한된 범위를 검색하는 경우
- 인덱스가 구성된 칼럼에서 무제한 범위를 검색하는 경우
- 정렬-병합 조인(Sort Merge)인 경우
- 인덱스가 구성된 칼럼에서 MAX 혹은 MIN을 구하는 경우
- 인덱스가 구성된 칼럼에서 ORDER BY를 실행하는 경우
- 전체 테이블을 스캔(FULL TABLE SCAN)하는 경우
비용 기반 옵티마이저(Cost base Optimizer)
- 오브젝트 통계 및 시스템 통계를 사용하여 총비용을 계산
- 총비용이 적은 쪽으로 실행 계획 수립
- 통계정보가 부적절한 경우 성능 저하가 발생할 수 있음
총비용: SQL문을 실행하기 위해 예상되는 소요시간 혹은 자원의 사용량
인덱스(Index)
- 데이터를 빠르게 검색할 수 있는 방법 제공
- 인덱스 키로 정렬되어 있기에 원하는 데이터를 빠르게 조회
- 오름차순 및 내림차순 탐색 가능
- 하나의 테이블에 여러 인덱스 생성 가능, 하나의 인덱스는 여러 칼럼으로 구성될 수 있음
- 테이블 생성시 기본키는 자동으로 인덱스가 만들며, 인덱스의 이름은 SYSXXXX
- 인덱스의 구조는 Root Block, Branch Block, Leaf Block으로 구성
인덱스의 구조
구조 | 설명 |
---|---|
Root Block | 인덱스 트레에서 가장 상위에 있는 노드 |
Branch Block | 다음 단계의 주소를 가지고 있는 포인터로 구성 |
Leaf Block | - 인덱스 키와 ROWID로 구성되며, 인덱스 키는 정렬되어 저장되어 있음 - Double Linked List 형태로 되어있어 양방향 탐색 가능 - 인덱스 키를 읽으면 ROWID를 사용하여 테이블의 행을 직접 읽을 수 있음 |
인덱스 생성
CREATE INDEX 인덱스이름 테이블 ON 테이블(칼럼1 정렬방법, 칼럼2 정렬방법)
정렬 방법을 생략하면 오름차순으로 정렬하며 'DESC'를 사용하면 내림차순 정렬 가능
인덱스 스캔
스캔 | 설명 |
---|---|
인덱스 유일 스캔 (Index Unique Scan) |
인덱스의 키 값이 중복되지 않는 경우, 해당 인덱스를 사용할 때 발생 |
인덱스 범위 스캔 (Index Range Scan) |
SELECT문에서 특정 범위를 조회하는 WHERE문을 사용할 경우 발생 |
인덱스 전체 스캔 (Index Full Scan) |
인덱스에서 검색되는 인덱스 키가 많은 경우 Leaf Block의 처음부터 끝까지 전체를 읽음 |
Hight Watermark: 테이블에 데이터가 저장된 블록에서 최상위 위치
실행 계획(Execution Plan)
- 부모자식 중에는 자식이우선
- 형제간에는 형이 우선
옵티마이저 조인(Optimizer Join)
Nested Loop 조인
- 하나의 테이블에서 데이터를 먼저 찾고 그다음 테이블을 조인하는 방식으로 실행
- 먼저 조회되는 테이블을 외부 테이블(Outer Table)이라 하며 그다음 테이블을 내부 테이블(Inner Table)이라 함
- 외부 테이블(선행테이블)의 크기가 작은 것을 먼저 찾는 것이 중요(데이터가 스캔되는 범위를 줄일 수 있기 때문)
- RANDOM ACCESS가 발생하며 RANDOM ACCESS가 많이 발생하면 성능 지연 발생
Sort Merge 조인
- 두 개의 테이블을 SORT_AREA라는 메모리 공간에 모두 로딩한 후 정렬(Sort) 수행
- 두 테이블의 정렬이 완료되면 두 개의 테이블을 병합(Merge)
- Sort Merge 조인은 정렬이 발생하기에 데이터양이 많아지면 성능이 떨어짐
- 정렬 데이터양이 너무 많으면 정렬은 임시 영역에서 수행
- 임시 영역은 디스크에 있기에 성능이 급격히 떨어짐
Hash 조인
- 두 개의 테이블 중 작은 테이블을 HASH 메모리에 로딩후 두 테이블의 조인 키를 사용하여 해시 테이블 생성
- 해시 함수를 사용하여 주소를 계산하고 해당 주소를 사용하여 테이블을 조인하기에 많은 CPU 연산 발생
- 선행 테이블이 충분히 메모리에 로딩되는 크기여야 함