비용기반 옵티마이저
비용기반(Cost-Based) 옵티마이저 (CBO)는 사용자 쿼리를 위해 후보군이 될만한 실행계획들을 도출하고, 데이터 딕셔너리에 미리 수집해둔 통계정보를 이용해 각 실행계획의 예상비용을 산정하고, 그중 가장 낮은 비용의 실행계획 하나를 선택하는 옵티마이저다.
CBO가 사용하는 통계정보
- 데이터양
- 컬럼 값의 수
- 컬럼 값의 분포
- 인덱스 높이,
- 클러스터링 팩터
규칙기반 옵티마이저
과거에는 각 액세스 경로에 대한 우선순위 규칙에 따라 실행계획을 만드는 옵티마이저를 사용했었다. (Rule-Base) 아까 CBO였으니까RBO겠지
데이터 특성을 나타내는 통계정보를 전혀 활용하지 않고 단순한 규칙에만 의존하기 때문에 대량 데이터를 처리하는데 부적합하다.
인덱스 구조, 연산자, 조건절 형태가 순위를 결정하는 주요소이다.
RBO가 사용하는 규칙 우선순위 및 규칙이다.
Single Row by Rowid -> Single Row by Cluster Join -> Single Row by Hash Cluster Key with Unique or Primary Key -> Single Row by Unique or Primary Key -> Clustered Join -> Hash Cluster Key -> Indexed Cluster Key -> Composite Index -> Single-Column Indexes -> Bounded Range Search on Indexed Columns -> Unbounded Range Search on Indexed Columns -> Sort Merge Join -> MAX or MIN of Indexed Column -> ORDER BY Indexed Column -> Full Table Scan 아 겁나 많네
옵티마이저 서브 엔진
- Query Transformer : 사용자로부터 전달받은 SQL을 그대로 최적화하지 않고 우선 최적화에 유리한 형태로 변환을 시도한다.
- Estimator : 쿼리 오퍼레이션 각 단계의 선택도 (Selectivity), 카디널리티 (Cardinality), 비용 (Cost)를 계산하고, 궁극적으로는 실행계획 전체에 대한 총 비용을 계산해 낸다.
- Plan Generator : 하나의 쿼리를 수행하는데 있어서, 후보군이 될만한 실행계획들을 생성해낸다.
통계정보
옵티마이저가 사용하는 통계정보로는 크게 오브젝트 통계와 시스템 통계가 있다.
오브젝트 통계로는
1. 테이블 통계 -> 레코드 수, 블록 수, 평균 행 길이
2. 인덱스 통계 -> 인덱스 높이, 리프 블록 개수, 클러스터링 팩터
3. 컬럼 통계 -> 중복을 제거한 컬럼 값의 수, 최소값, 최대값, Null 값 개수, 히스토그램
또한
CPU 속도, Single Block I/O 속도, Multiblock I/O 속도, 평균적인 Multiblock I/O 개수 등을 관리한다.
오라클 11g에서 도입된 Adaptive Direct Path Read 기능이 Direct Path Read를 사용할지 여부를 결정할 때 고려하는 항목 중 하나가 버퍼캐시 크기이다. 이는 실행계획을 수립할 때가 아니라 런타임시 고려사항이다.
최초 응답속도 최적화가 효과적인 애플리케이션 아키텍쳐는 주로 2-Tier 환경의 클라이언트/서버 구조다. 이 애플리케이션 구조의 특징은 전체 결과집합이 아무리 많아도 사용자가 스크롤을 통해 일부만 Fetch 하다가 멈출 수 있다는 점이다. 결과집합을 끝까지 Fetch 하거나 다른 쿼리를 수행하기 전까지 SQL 커서는 오픈된 상태를 유지한다.
반면, OLTP성 애플리케이션이라더라도 3-Tier 구조는 클라이언트와 서버 간 연결을 지속하지 않는 환경이므로 오픈 커서를 계속 유지할 수 없어 일반적으로 페이징 처리 기법을 사용한다. 이를 위해 rownum으로 결과집합을 10~20건으로 제한하는 쿼리를 사용한다. 대량 데이터 중 일부만 Fetch하다가 멈추는 것이 아니라 집합 자체를 소량으로 정의해서 모두 Fetch 한다면, 전체 처리속도 최적화가 더 적절한 설정이다.
결론적으로, OLTP성 애플리케이션이더라도 아키텍처에 따라 최적화 목표는 다를 수 있다 그렇군
옵티마이저 행동에 영향을 미쳐버리는 요소 (쿼리 성능에 영향을 미치는 요소) 아주 미쳐버릴거같다.
- 옵티마이저 팩터 : 인덱스, IOT, 클러스터링, 파티셔닝 등 오브젝트 구성
- DBMS 제약 설정 : PK, FK, Check, Not Null
- 통계정보
- 옵티마이저 힌트
- 옵티마이저 관련 파라미터
옵티마이저의 한계 ㅉㅉ
옵티마이저가 항상 최적의 실행계획을 생성하지 못하는 데는 아래와 같은 이유가 있다.
- 부족한 옵티마이징 팩터 : 인덱스, IOT, 클러스터링, 파티셔닝 등 오브젝트 구성
- 부정확한 통계 : 정보 수집 및 보관 비용 측면의 한계 (샘플링 비율, 수집 주기 등)
- 결합 선택도 산정의 어려움
- 바인드 변수 사용시, 히스토그램 사용에 제약 : 균등분포 가정
- 비현실적인 가정과 규칙에 의존
- 최적화 시간에 허용된 시간 제약
온라인 옵티마이저는 정해진 시간 내에 빠르게 최적화를 수행해야하기 때문에 정보를 충분히 활용하지 못한다. 오라클의 경우 튜닝 모드에서 오프라인 옵티마이저(=자동 튜닝 옵티마이저)를 구동하면, 시간 제약없이 다이나믹 샘플링을 포함한 다양한 정보와 기법을 활용하므로 훨씬 더 완벽한 실행계획을 생성한다
라이브러리 캐시 공간의 크기는 옵티마이저가 생성하는 실행계획에는 영향을 주지않는다. 공간이 부족하면 SQL 실행계획이 캐시에서 자주 밀려나므로 파싱과 최적화를 자주 수행함으로 인한 부하가 늘어날뿐
선택도와 카디널리티
선택도 : 전체 레코드 중에서 조건절에 의해 선택되는 레코드 비율을 말한다. 연산자 종류에 따라 선택도 구하는 방식이 다른데, 가장 단순한 '=' 조건으로 검색하는 경우만 살펴보면
선택도 = 1 / NDV (넘버 오브 디스틴트 밸류스 컬럼 값 종류 개수)
카디널리티 : 전체 레코드 중에서 조건절에 의해 선택되는 레코드 개수
카디널리티 : 총 로우 수 x 선택도 = 총 로우수 / NDV
컬럼 통계
오라클에서 수집하는 컬럼 통계 항목들
- 중복을 제거한 컬럼 값의 수 (num_distinct)
- 최소값 (low_value)
- 최대값 (high_value)
- 밀도 (density)
- 평균 컬럼 길이 (avg_col_len)
- NULL 값을 가진 레코드의 수 (num_nulls)
시스템 통계
애플리케이션 및 하드웨어 성능 특성을 측정한 겂
- CPU 속도
- 평균적인 Single Block I/O 속도
- 평균적인 Multiblock I/O 속도
- 평균적인 Multiblcok I/O 개수
- I/O 서브시스템의 최대 처리량 (Throughput)
- 병렬 Slave 평균적인 처리량 (Throughput)
I/O 비용 모델 vs CPU 비용 모델
I/O 비용 모델의 비용은 예상되는 디스크 I/O Call 횟수를 의마한다.
CPU 비용 모델에서는 예상 I/O 시간과 예상 CPU 사용시간을 구한 후 Single Block I/O 시간으로 나눈 값을 비용 값으로 사용한다. 즉 비용을 Single Block I/O에 소요되는 시간과의 상대적인 시간 비용으로 표현한 것이다.
히스토그램 유형 (와 이런거까지 알아야되네)
- 도수분포 (Frequency) : 값별로 빈도수 저장
- 높이균형 (Height-Balanced) : 각 버킷의 높이가 동일하도록 데이터 분포 관리
- 상위도수분포 (Top-Frequency) : 많은 레코드를 가진 상위 n개 값의 빈도수 저장
- 하이브리드(Hybrid) : 도수분포와 높이균형 히스토그램의 특성을 결합
인덱스를 이용한 테이블 액세스 비용
비용 = 브랜치 레벨
+ (리프 블록 수 x 유효 인덱스 선택도)
+ (클러스터링 팩터 x 유효 테이블 선택도)
유효 인덱스 선택도는 인덱스 총 레코드 중에서 조건절을 만족할 것으로 예상되는 레코드 비율
유효 테이블 선택도는 전체 인덱스 레코드중에서 인덱스 스캔을 원료하고서 테이블을 방문할 것으로 예상되는 레코드 비율
손꾸락 아파죽겠다