DataBase Index - Mysql
by SoonYong Hong
Index
목차
- 인덱스 기본
- Clustered Index & Nonclustered Index
- InnoDB Index
- 인덱스 활용하기
인덱스 기본
대부분의 DBMS에서 인덱스는 B-Tree 구조를 가지고 있다.
트리의 각 노드에는 인덱스 키와 자식노드의 주소를 key:value 셋의 형태로 가지고 있으며 마지막 리프노드에는 인덱스 키와 데이터 주소를 가지고 있게된다.
각 노드에는 같은 레벨의 다음노드와 이전노드를 오갈수 있는 링크를 가지고 있다.
인덱스를 이용한 레코드 검색은 루트노드부터 리프노드까지 해당하는 키를 찾아서 탐색하여 리프노드에 도달한뒤 획득한 데이터 주소를 이용하여 row 전체를 획득한다.
| 루트 노드 | 브랜치 노드 | 리프 노드 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
↑ ↓
|
↑ ↓
↑ ↓
↑ ↓
|
Clustered Index & Nonclustered Index
Clustered Index
클러스터 인덱스는 데이터를 따로 저장하지 않고 인덱스의 리프노드에 데이터를 저장하는 방식입니다.
클러스터 인덱스는 데이터 자체를 포함하고 있기 때문에 단 한개만 생성할 수 있습니다.
| 루트 노드 | 브랜치 노드 | 리프 노드 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
↑ ↓
|
↑ ↓
↑ ↓
↑ ↓
|
Nonclustered Index
넌클러스터 인덱스는 데이터를 따로 저장해두고 리프노드에 데이터의 주소를 저장하는 방식입니다.
클러스터 인덱스와 달리 여러개를 생성할 수 있습니다.
| 루트 노드 | 브랜치 노드 | 리프 노드 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
↑ ↓
|
↑ ↓
↑ ↓
↑ ↓
|
| 주소 | 데이터 |
| ... | ... |
| 12027 | Job,1개,직업,$10000 |
| ... | ... |
| 12314 | Apple,10개,사과,10 |
| ... | ... |
| 12321 | Banana,20개,바나나,12 |
| ... | ... |
| 12647 | Egg,10개,계란,1 |
| ... | ... |
| 13339 | Keep,null,보관,null |
| ... | ... |
| 13456 | Golf,null,골프,null |
| ... | ... |
| 13458 | Farm,2개,농장,1000000 |
| ... | ... |
| 14509 | Iter,null,반복,null |
| ... | ... |
| 15228 | Half,null,절반,null |
| ... | ... |
InnoDB 인덱스
Mysql InnoDB에서는 클러스터 인덱스와 넌클러스터 인덱스 모두를 사용한다.
테이블을 생성하면 자동으로 PK을 인덱스 키로하는 클러스터 인덱스가 생성된다.
그 외 모든 인덱스는 넌클러스터 인덱스로 생성되며 이 넌클러스터 인덱스의 리프노드에는 데이터의 주소대신에 PK가 저장되어 있다.
즉 넌클러스터 인덱스를 이용하여 PK를 조회하고 클러스터 인덱스와 PK를 이용하여 데이터를 획득한다.
클러스터 인덱스
| 루트 노드 | 브랜치 노드 | 리프 노드 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
↑ ↓
|
↑ ↓
↑ ↓
↑ ↓
|
넌클러스터 인덱스
| 루트 노드 | 브랜치 노드 | 리프 노드 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
↑ ↓
|
↑ ↓
↑ ↓
↑ ↓
|
인덱스 활용하기
Mysql 인덱스를 활용하는 방법
커버링 인덱스
커버링 인덱스는 쿼리를 실행하는데 필요한 모든 데이터를 인덱스에서 추출할 수 있는 경우를 말합니다.
일반적으로 페이지네이션에 주로 사용합니다.
SELECT * FROM myTable ORDER BY index_key_part1 DESC LIMIT 1000, 10;
위 쿼리는 일반적으로 사용하는 페이지네이션 쿼리입니다. 이 경우 filesort를 사용하여 쿼리가 실행됩니다.
SELECT * FROM myTable AS b JOIN (SELECT pk FROM myTable ORDER BY index_key_part1 DESC LIMIT 1000, 10) AS a ON a.pk = b.pk;
위 쿼리는 index search를 이용하여 쿼리가 실행됩니다.
index_key와 넌클러스터 인덱스를 사용하여 PK를 획득하고 PK와 클러스터 인덱스를 이용하여 실제 데이터를 획득하게 됩니다.
주의 사항
인덱스 key의 순서에 맞게 사용해야 합니다.
SELECT pk FROM myTable ORDER BY index_key_part1, index_key_part2, index_key_part3
SELECT count(pk) FROM myTable GROUP BY index_key_part1, index_key_part2
SELECT pk FROM myTable ORDER BY index_key_part1
SELECT pk FROM myTable WHERE index_key_part1 = 1 ORDER BY index_key_part2, index_key_part3
위 쿼리는 모두 index search를 사용하여 실행됩니다.
SELECT pk FROM myTable ORDER BY index_key_part2, index_key_part1, index_key_part3
SELECT count(pk) FROM myTable GROUP BY index_key_part2, index_key_part3
SELECT pk FROM myTable ORDER BY index_key_part2
위 쿼리는 모두 filesort를 사용하여 실행됩니다.
Subscribe via RSS