- 목차
- 08. 인덱스
- 디스크 읽기 방식
- 인덱스란?
- B-Tree 인덱스
- R-Tree 인덱스
- 전문 검색 인덱스
- 함수 기반 인덱스
- 멀티 밸류 인덱스
- 클러스터링 인덱스
- 유니크 인덱스
- 외래키
- 09. 옵티마이저와 힌트 & 10. 실행 계획
- 개요
- 개요
- 08. 인덱스
08. 인덱스
데이터베이스 쿼리의 성능을 언급하면서 빼놓을 수 없는 부분이다.
디스크 읽기 방식
순차, 랜덤 I/O 방식이 존재하며 데이터베이스에서는 보통 랜덤 I/O의 비중이 더 크다.
인덱스란?
색인, 지표 등으로 번역되는 인덱스는 조회 성능을 향상시키는데 주요한 역할을 하는 기능이다.
다만 이때, 조회 성능을 위한 데이터 정렬, 유지 비용 등이 발생하기 때문에 저장 성능에는 악영향을 끼친다. 따라서 너무 많아도 좋지 않다.
인덱스의 종류는 역할(프라이머리/보조), 저장 방식(자료구조), 데이터 중복 허용(유니크), 기능(공간 검색, 전문 검색 등) 등으로 나뉜다.
B-Tree 인덱스
인덱싱 알고리즘 가운데, 가장 먼저 도입된 알고리즘으로, 현재도 범용적으로 사용되는 알고리즘이다.
여러 변형된 형태가 존재하며 DBMS에는 주로 B+Tree, B*Tree가 사용된다.
- 구조 및 특성
- 일단은 트리 구조로, 최상단의 루트 노드와, 최하단의 리프 노드, 그 사이의 브랜치 노드로 이뤄진다.
- 루트 노드와 브랜치 노드는 각 인덱스의 키와 그에 따른 자식 노드의 주소를 값으로 가지며 리프 노드는 해당 인덱스 키와 프라이머리 키를 값으로 가진다.
- 최종적으로 프라이머리 키를 가지고 프라이머리 인덱스에 질의한 후, 프라이머리 인덱스의 리프 페이지에서 해당 레코드를 읽는다.
- B-Tree 인덱스를 통한 데이터 읽기
- 인덱스 레인지 스캔
- 검색해야 할 인덱스의 범위가 결정되었을 때, 사용하는 방식으로, 루트와 브랜치 노드를 통해 스캔을 시작할 지점을 찾고 조건에 맞는 값들을 순차적으로 스캔하다. 범위 조건이 종료되거나 인덱스의 끝에 도달하면 중단한다.
- 인덱스 풀 스캔
- 말 그대로 리프 노드의 처음부터 끝까지 모든 데이터를 순차적으로 읽는 것이다.
- 대표적으로, 인덱스가 걸려있는 특정 값을 전부 조회할 때 사용된다.
- 루스 인덱스 스캔
- 루스 인덱스 스캔은 인덱스를 사용해 모든 데이터를 읽지 않고 필요한 값만 읽어오는 최적화 기법이다.
- 기본적으로 인덱스 레인지 스캔과 유사하나 조건에 부합하는 값만 읽는다는 점이 다르다. 이때문에 인덱스 레인지 스캔을 타이트 인덱스 스캔이라고도 부른다.
- GROUP BY, DISTINCT, MIN, MAX와 같은 특정 연산에서 최적화 시 사용한다.
- 인덱스 스킵 스캔
- 인덱스 스킵 스캔은 다중 컬럼 인덱스에서 선행 컬럼에 대한 조건이 없을 때도, 후행 컬럼을 활용하여 필요한 데이터를 효율적으로 검색하는 최적화 기법이다.
- 인덱스 레인지 스캔
R-Tree 인덱스
공간 인덱스라고도 불리며, 공간 데이터와 관련한 여러 기능들을 제공한다.
주로 위도, 경도 좌표 저장에 사용되며 특정 점이 범위에 포함되는 지 등의 연산도 제공한다.
전문 검색 인덱스
일반적이 인덱스와 달리, 특정 키워드가 포함된 문서를 검색하는 인덱스다.
ElasticSearch의 미니미 버전? 스펙이 제한적인 상황에서 검색의 퀄리티, 조회 성능을 올려야할 때 선택해볼 수 있을 것 같다.
함수 기반 인덱스
함수를 사용하여 생성되는 인덱스로, 테이블의 구조를 변경하지 않고 함수의 결괏값을 토대로 인덱스를 생성한다.
조회 시, 함수 기반 인덱스를 생성할 때 사용했던 수식을 그대로 사용해주어야 정상적으로 동작한다.
클러스터링 인덱스
MySQL 서버에서의 클러스터링 인덱스는, InnoDB 스토리지 엔진에서만 지원한다.
프라이머리 키에 한해서 적용되는 인덱스로 알고리즘보다는 데이터 저장방식에 더 가깝다.
유니크 인덱스
제약조건에 가까운 인덱스로 말 그대로 테이블이나 인덱스에 같은 값이 2개 이상 저장될 수 없음을 의미한다.
NULL은 데이터로 저장이 가능하며 특정 값이 아니므로 2개 이상이 존재할 수 있다.
09. 옵티마이저와 힌트 & 10. 실행 계획
개요
옵티마이저는 SQL 파스 트리를 참조하여 최적화 및 실행 계획을 수립한다.
이때, 옵티마이저의 종류는 최적화 기법에 따라 나뉘는데, 규칙, 비용 기반이 존재하며 현재 대부분의 DBMS는 비용 기반 최적화를 사용한다.
8.0 버전 이후의 변경 사항은 다음과 같다.
- 히스토그램
- 테이블의 컬럼 값 분포를 통계적으로 표현해 옵티마이저의 실행 계획을 돕는 히스토그램이 추가되었다.
- 메모리 I/O와 디스크 I/O 간의 비용 분리 계산
- 이전 버전에는 모든 I/O 비용을 동일하게 간주하여, 메모리와 디스크의 성능 차이를 충실히 반영하지 못했으나 8.0부터는 별도로 계산하게 되었다.
- 덕분에 옵티마이저는 데이터가 InnoDB의 버퍼 풀에 있는 경우와 디스크에서 읽어와야하는 경우를 나눠 더 효율적인 실행계획을 수립할 수 있다.
- FORCE INDEX를 이용한 특정 인덱스 사용 강제
- 특정 인덱스 사용을 강제하는 방법으로 인덱스 다이브의 과정을 단축시켜준다.
- 새로운 힌트들
- MERGE, INDEX_MERGE 등 새로운 힌트들이 추가되었다.
- LIKE 연산자 사용시, 프리픽스 인덱스를 커버링 인덱스로 고려
- Covering Prefix Index를 사용하여 전방 매칭이 포함된 조건에서 프리픽스 인덱스를 사용해 성능을 최적화한다.
- 전방 매칭인 경우, 인덱스를 타지 않았던 것이 아니라 효율적인 실행 계획을 만들지 못했으나 8.0 이후 버전부터는 커버링 인데스를 더 적극적으로 사용하는 것이다.
- 즉, 쿼리를 분석해 추가적인 테이블 조회가 필요없는 경우 생략한다.
- Covering Prefix Index를 사용하여 전방 매칭이 포함된 조건에서 프리픽스 인덱스를 사용해 성능을 최적화한다.