Skip to content

Commit

Permalink
Merge pull request JAVACAFE-STUDY#33 from minenam/week7
Browse files Browse the repository at this point in the history
[week07] 남혜민
  • Loading branch information
sazzeo authored Nov 14, 2024
2 parents dd09565 + 833eecc commit 4d316dd
Showing 1 changed file with 100 additions and 0 deletions.
100 changes: 100 additions & 0 deletions 09장/9_옵티마이저와_힌트_남혜민.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# 개요

### 쿼리 실행 절차

1. SQL 파싱(parsing) : SQL 파서로 모듈 처리. SQL 문장을 서버가 이해할 수 있는 수준으로 분리
2. 최적화 및 실행계획 수립: 옵티마이저가 처리. SQL 파스트리를 통해 실행계획 (테이블/인덱스 등) 생성
3. 스토리지 엔진에 데이터 요청 및 처리: 실행계획에 따라 스토리지 엔진에서 데이터를 가져와 처리

### 옵티마이저의 종류

- 비용 기반 최적화(Cost-based optimization, CBO) : 최신
- 규칙 기반 최적화(Rule-based optimization, RBO) : 예전 오라클에서 사용

# 기본 데이터 처리

### 플 테이블 스캔과 풀 인덱스 스캔

- 풀 테이블 스캔: 테이블 전체를 읽어서 처리
- 풀 인덱스 스캔: 인덱스 전체를 읽어서 처리

### 병렬 처리

### ORDER BY 처리(Using filesort)

- 인덱스 이용: 인덱스를 순서대로 읽기만 하면 되서 매우 빠르나 추가/삭제 작업이 느리고 디스크 공간이 많이 필요
- Filesort 이용: 인덷스를 생성하지 않아도 돼 정렬할 레코드 많지 않으면 메모리에서 처리되어 충분히 빠름. 그러나 레코드 건수가 많아질수록 쿼리 응답 속도가 느림

#### 소트 버퍼

- 정렬을 수행하기 위해 할당 받은 별도의 메모리 공간
- 쿼리 실행 완료되면 시스템으로 반납

#### 정렬 알고리즘

- 투 패스(Two-pass)
- 정렬 키와 레코드의 로우 아이디(row ID)만 가져와서 정렬
- 정렬 대상 칼럼과 프라이머리 키값만 소트 버퍼에 정렬 수행하고 FK 키로 SELECT 컬럼 조회
- 테이블을 2번 불러와야 함
- 정렬 대상 레코드의 크기나 건수가 많을 때 효율적
- 싱글 패스(Single-pass)
- 정렬 키와 레코드 전체를 가져와서 정렬
- 소트 버퍼에 정렬 기준 칼럼을 포함한 SELECT 문의 칼럼을 모두 정렬 수행
- 더 많은 소트 버전 필요
- 최신 버전에서 주로 사용
- 정렬 대상 레코드의 크기나 건수가 적을 때 빠른 성능을 보임

#### 정렬 처리 방법

1. 인덱스를 사용한 정렬
2. 조인에서 드라이빙 테이블만 정렬: Using filesort, 드라이빙 테이블만 검색해서 정렬을 먼저 수행하고 결과와 드리븐 테이블을 조인
3. 조인에서 조인 결과를 임시 테이블로 저장 후 정렬: Using temporary;Using filesort

**쿼리 처리 방식**

- 스트리밍: 조건 일치하는 레코드 검색되면 바로 클라에 전송. 첫 번째 레코드를 바로 전달받아 빠른 응답 시간 보장. LIMIT 으로 시간 단축 가능
-> 인덱스를 사용한 정렬 방식
- 버퍼링: 모든 레코드를 검색하고 일괄 가공해야 함. LIMIT있어도 성능 안 됨 ex) GROUP BY, ORDER BY 등
-> 조인에서 드라이빙 테이블만 정렬, 임시테이블을 이용한 정렬 방식

#### 정렬 관련 상태 변수

- 상태 변수: 작업의 실행 횟수 저장(정렬, 소프 버퍼 간 병합 작업 횟수 등)

### GROUP BY 처리

- 인덱스 스캔 이용하는 GROUP BY (타이트 인덱스 스캔) : 그루핑 컬럼에 인덱스가 있다면 차례로 읽어 처리
- 루스 인덱스 스캔 이용하는 GROUP BY (루스 인덱스 스캔) : 인덱스 레코드를 건너 뛰며 필요한 부분만 읽어서 가져옴 (Using index for group-by), 단일 테이블에 대한 처리만 사용 가능, 프리필스 인덱스 사용 불가, 유니크한 인덱스 수가 적을 수록 향상 = 인덱스 스킵 스캔 도입 (8.0)
- 임시 테이블 사용 방법 : 그루핑 칼럼이 인덱스를 전혀 사용 못할 때. Group by 칼럼들로 구성된 유니크 인덱스를 가진 임시테이블 만들어 가공

### DISTINCT 처리

#### 집합 함수 없는 SELECT DISTINCT ...

GROUP BY 와 동일하게 처리
SELECT 절에 사용된 DISTINCT 키워드는 조회되는 모든 칼럼의 조합이 유니크한 것을 가져옴

#### 집합 함수와 함께 사용된 DISTINCT

집합 함수에 사용된 인자의 컬럼 값이 유니크한 것을 가져와 임시 테이블 사용

### 내부 임시 테이블 활용

MySQL 엔진이 스토리지 엔진으로 받은 레코드를 정렬하거나 그루핑할 때 내부적인 임시 테이블 (Internal Temporary Table)을 사용.
메모리에 생성됐다가 테이블 크기 커지만 디스크로 이동, 쿼리 처리 완료되면 자동 삭제

#### 메모리 임시 테이블과 디스트 임시 테이블

8.0 부터 메모리는 가변길이 지원하는 TempTable, 디스크는 트랜잭션 지원 가능한 InnoDB 스토리지 엔진으로 변경됨

# 고급 최적화

### 옵티마이저 스위치 옵션

### 조인 최적화 알고리즘

# 쿼리 힌트

### 인덱스 힌트

### 옵티마이저 힌트

0 comments on commit 4d316dd

Please sign in to comment.