Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
234 changes: 234 additions & 0 deletions 9week/byungil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
# 7.1 통계 정보와 비용 계산 원리

## 7.1.1 선택도와 카디널리티

## 선택도와 카디널리티의 관계

### 선택도

- 전체 레코드 중에서 조건절에 의해 선택되는 레코드 비율

### 컬럼 값 종류 개수 (Number of Distinct Value)

- `=` 조건일 때

```
선택도 = 1 / NDV
```


### 카디널리티

```
카디널리티 = 총 로우 수 * 선택도 = 총 로우 수 / NDV
```

<aside>
💡 **카디널리티 의미는 DBMS마다 다르다.**

오라클에서 말하는 카디널리티와 일반적인 카디널리티는 차이가 있습니다.
오라클은 특정 액세스단계를 거치고 나서 나오는 결과 건수를 보통 말하는 것입니다.
모델링의 카디널리티나 힌트의 카디널리티도 비슷한 맥락이라고 보시면 됩니다.

'카디널리티'의 의미도 DBMS마다 다릅니다. **오라클에서는 위에서 말씀드린 것처럼 '전체 레코드 중 조건절을 만족하는 레코드 개수'를 의미**하지만, MySQL에서는 특정 컬럼의 값의 종류 개수(NDV, Number of Distinct Values)를 의미합니다.

</aside>

### 예시

> 상품분류 컬럼에 가전, 의류, 식음료, 생활용품 네 개의 값이 존재하고, 전체 레코드가 10만건
>
- `where 상품분류 = '가전'` 조건절
- NDV = 4
- 선택도 = 1 / 4 = 0.25
- 카디널리티 = 100,000 * 0.25 = 25,000

## 옵티마이저와 카디널리티

- 옵티마이저는 카디널리티를 계산하고, 그만큼의 데이터를 액세스하는 데 드는 비용을 계산한다.
- 계산한 값을 기반으로 테이블 액세스 방식, 조인 순서, 조인 방식 등을 결정한다.

### 선택도가 가장 중요

- 비용 계산의 시작점이기 때문이다.
- 선택도를 계산할 때 NDV를 사용하므로 이 값을 정확히 구하는 것이 매우 중요하다.
- 통계 정보 수집 주기, 샘플링 비율 등을 잘 결정해야 한다.

## 7.1.2 통계 정보

## 오브젝트 통계

### 테이블 통계

- 저장된 총 레코드 개수
- 테이블 블록 수
- 사용된 익스텐트에 속한 총 블록 수
- 레코드 당 평균 길이
- 샘플링한 레코드 수
- 통계정보 수집 일시

### 인덱스 통계

- 인덱스 수직적 탐색 비용 계산
- 브랜치 뎁스
- 인덱스 수평적 탐색 비용 계산
- 인덱스 리프 블록 총 개수
- 인덱스에 저장된 레코드 개수
- 인덱스의 키와 값의 조합으로 만들 수 있는 값의 개수
- 인덱스 키 값을 모두 `=` 조건으로 조회할 때 읽게 될 리프 블록 개수
- 테이블 액세스 비용 계산
- 인덱스 키 값을 모두 `=` 조건으로 조회할 때 읽게 될 테이블 블록 개수
- 인덱스 키값 기준으로 테이블 데이터가 모여있는 정도

### 컬럼 통계 (히스토그램 포함)

- 컬럼 값의 종류 개수 (NDV)
- ex: 성별 컬럼의 경우 NDV = 2
- `=` 조건으로 검색할 때의 선택도를 미리 구해 놓은 값 (`1/NDV`)
- 컬럼 평균 길이
- 최소 값
- 최대 값
- 값이 NULL인 레코드 수
- 컬럼 히스토그램
- 컬럼 값 별로 데이터 비중 또는 빈도를 미리 계산해 놓은 통계 정보
- 실제 데이터를 읽어서 계산해둔 값
- 데이터 분포가 많이 변하지 않으면 거의 정확함
- 사용 이유
- 선택도를 잘못 구하면 액세스 비용을 잘못 산정하여 최적이 아닌 실행 계획으로 이어짐
- 데이터 분포가 균일하지 않을수록 잘못 구할 확률이 높아짐
- 옵티마이저는 데이터 분포가 균일하지 않은 컬럼에 히스토그램을 이용함
- 타입
- 도수분포 : 값 별 빈도수 저장
- 높이 균형 : 각 버킷 높이가 동일하도록 데이터 분포를 관리
- 상위도수분포 : 많은 레코드를 가진 상위 N개 값에 대한 빈도수 저장
- 하이브리드 : 도수분포 + 높이균형

## 시스템 통계

- 애플리케이션 및 하드웨어 성능 특성을 측정한 것

### 정보

- CPU 속도
- 평균 Single Block I/O 속도
- 평균 Multiblock I/O 속도
- 평균 Multiblock I/O 개수
- I/O 서브 시스템의 최대 처리량
- 병렬 Slave의 평균 처리량

## 7.1.3 비용 계산

- 인덱스 통계, 유효 인덱스 선택도, 유효 테이블 선택도 등의 정보를 이용하여 계산

## 비용 모델

### I/O 비용 모델

- 비용 = 예상 I/O Call 횟수를 의미

### CPU 비용 모델

- 비용 = Single Block I/O를 기준으로 한 상대적 시간을 의미
- 같은 실행계획으로 같은 양의 데이터를 읽어도, 애플리케이션 및 하드웨어 성능 특성에 따라 절대 소요시간이 달라지기 때문에 CPU 비용 모델을 개발했음

# 7.2 옵티마이저에 대한 이해

## 7.2.1 옵티마이저 종류

## 규칙 기반(Rule-Based) 옵티마이저

- 통계 정보를 이용하지 않고, 단순한 규칙에만 의존하여 데이터를 처리
- 대량 데이터 처리에 부적합
- 한계
- 최적의 실행계획 계산에 무리가 있다 (무조건 정해진 대로만 행동)

## 비용 기반(Cost-Based) 옵티마이저

- 규칙 기반 옵티마이저의 한계로 인해 개발된 옵티마이저

### 동작 방식

1. 사용자 쿼리를 위해 후보군이 될만한 실행 계획들을 도출
2. 데이터 딕셔너리에 미리 수집해 둔 통계 정보를 이용해 각 실행계획의 예상 비용 산정
3. 그중 가장 낮은 비용의 실행계획 하나를 선택

## 7.2.2 옵티마이저 모드

> 목적에 따라 옵티마이저 모드를 잘 설정해야 한다
>

## 종류

### ALL_ROWS

- 전체 처리 속도 최적화

### FIRST_ROWS(deprecated)

- 최초 응답 속도 최적화
- 결과 집합 전체를 읽어야 하는 경우, 전체 수행 속도가 느려질 수 있음

### FIRST_ROWS_N

- 최초 N건 응답 속도 최적화

## 옵티마이저에 영향을 미치는 요소

- SQL과 연산자 형태
- SQL을 어떤 형태로 작성했는지 또는 어떤 연산자를 사용했는지
- 인덱스, IOT, 클러스터, 파티션, MV 등 옵티마이징 팩터
- 같은 쿼리도 팩터 구성에 따라 실행계획과 성능이 달라짐
- 제약 설정
- PK, FK, Check, Not Null 같은 제약들은 무결성을 보장해줄 분만 아니라, 옵티마이저가 쿼리 성능을 최적화하는 데 매우 중요한 메타 정보로 활용됨
- 통계 정보
- 잘 작동하던 프로그램이 갑자기 느려진 경우 대부분 통계 정보가 원인임
- 특정 테이블 통계정보가 갑자기 삭제된 경우
- 대량 데이터를 지웠다가 다시 입력하기 직전, 데이터가 없는 상태에서 자동으로 통계 정보가 수집된 경우
- 3년간 갱신하지 않았던 특정 테이블의 통계 정보를 갑자기 재수집 하는 경우
- 통계 정보 없이 관리하던 테이블에 인덱스를 재생성 하는 경우
- 옵티마이저 힌트
- 옵티마이저 관련 파라미터
- 파라미터 추가 또는 기본 값 변경으로 인해 다르게 작동할 수 있음

## 옵티마이저의 한계

- 옵티마이저도 실수를 한다
- 옵티마이저의 선택은 항상 최선인 것은 아니다
- 통계 정보를 필요한 만큼 충분히 확보하는 것은 불가능하다
- 기본적으로 비용 기반이나, 내부적으로 여러 가정과 정해진 규칙을 통해 기계적인 선택을 한다
- 판단이 애매할 경우 규칙들이 오히려 현실에 안맞을 수 있다
- 최적화에 허용되는 시간이 매우 짧다

## 개발자의 역할

- 개발자 스스로가 옵티마이저가 되어야 한다
- 결과물이 올바른지 실행계획을 통해 늘 점검하고 개선 포인트가 없는지를 찾으려 노력하자
- 필요한 최소 블록만 읽도록 쿼리를 작성하자
- 결과 집합을 논리적으로 잘 정의하고, DB 프로세스가 최소한의 일만 하도록 효율적인 쿼리를 작성해야 한다 (I/O 효율을 증가시키자!)
- 최적의 옵티마이징 팩터를 제공하자
- 옵티마이저가 최적화를 잘 수행하도록 적절한 수단을 제공하자
- 옵티마이징 팩터
- 전략적인 인덱스 구성
- DBMS가 제공하는 다양한 기능 활용
- 적절한 옵티마이저 모드 설정
- 정확하고 안정적인 통계 정보
- 필요하다면, 옵티마이저 힌트를 통해 최적의 액세스 경로로 유도하자

## 데이터베이스 튜닝

### SQL 튜닝

- I/O 효율화
- DB Call 최소화
- SQL 파싱 최소화

### DB 설계

- 논리적 데이터 구조 설계
- 물리적 저장 구조 설계

### 인스턴스 튜닝

- Lock/Latch 모니터링 및 해소
- 메모리 설정
- 프로세스 설정