Post

클러스터, 논클러스터 인덱스

인덱스란?

인덱스는 테이블의 컬럼을 색인화 함으로서 책의 목차와 유사한 기능을 제공한다. 데이터를 정렬 후 별도의 메모리 공간에 저장하는데, 이 형태는 key, value 쌍으로 구성된다.

인덱스를 저장하는 방식에도 종류가 있는데, 대표적으로 클러스터형 인덱스와 논클러스터형 인덱스로 구분할 수 있다.

클러스터 인덱스

cluster

클러스터 인덱스는 데이터를 순차적으로 재배치한다. 대표적으로 MySQL에 해당 방식이 기본적으로 사용되고 있다.

primary key를 설정하면 해당 컬럼은 자동으로 클러스터드 인덱스가 구성되며, 데이터를 물리적으로 정렬해서 저장한다. 이를 활용하여 빠르게 데이터를 가져오는 방식이다.

정렬된 데이터 테이블을 참조하기 때문에 검색 속도는 빠르지만, 신규 데이터를 중간에 입력하거나 삭제하는 경우 다시 테이블을 정렬해야 하기 때문에 성능저하가 올 수 있다.

논 클러스터 인덱스

non-cluster

논클러스터 인덱스는 인덱스 키와 위치를 참조하는 포인터를 가지고 있다. 데이터를 따로 정렬해 놓지 않고, 정리된 인덱스 테이블의 정보로 데이터에 접근한다. PostgreSQL이 해당 방식을 채택하고 있다.

실제 테이블을 정렬하는 것이 아니기 때문에 데이터 추가, 삭제에 대해 클러스터 인덱스보다 영향이 적지만 인덱스 테이블 조회, 포인터 접근, 데이터 읽기 등의 비교적 더 많은 I/O 작업이 수행될 수 있다.

인덱스 vs 풀 테이블 스캔

인덱스도 별도의 테이블을 생성해서 참조한다는 것을 확인할 수 있었다. 그렇다면 인덱스 테이블을 참조하는 것과 그냥 테이블을 풀스캔 하는것은 왜 그렇게 퍼포먼스 차이가 나는 것일까? 해외 사이트에서 간단한 예시가 보여서 가져와봤다.

idname
1Matt
2Dave
3Andrew
4Todd
5Blake
6Evan
7Nick
8Zack

다음과 같은 friends 테이블이 존재한다고 가정하고, 아래와 같은 쿼리를 실행한다고 해보자.

1
SELECT * FROM friends WHERE name = 'Zack';

풀스캔

name탐색순서
Matt1
Dave2
Andrew3
Todd4
Blake5
Evan6
Nick7
Zack8

Zack을 탐색하기 위해서는 Matt부터 순차적으로 이름을 비교해보아야 한다. Zack은 테이블의 가장 마지막에 위치하고 있기 때문에, 테이블을 처음부터 끝까지 스캔해야 알 수 있는 그야말로 최악의 성능을 보이게 될 것이다.

지금은 데이터가 8개밖에 되지 않기 때문에 8번만 비교해보면 Zack을 찾을 수 있지만, 데이터의 양이 증가할수록 탐색해야 하는 범위는 비례하게 늘어날 수 밖에 없다.

인덱스

만약 이름을 기준으로 인덱스가 걸려있다면 어떤 방식으로 탐색이 가능할까?

name
Andrew
Blake
Dave
Evan
Matt
Nick
Todd
Zack

데이터는 다음과 같이 정렬되어 있을 것이고, Zack은 동일하게 테이블의 가장 마지막에 위치하고 있다. 하지만 차이점이 있다면, ‘정렬된 데이터’라는 보장이 있다는 것이다. 데이터가 정렬되어 있기 때문에, 이분 탐색과 같은 방식을 사용할 수 있고, 검색 성능이 크게 향상될 수 있다.

name탐색순서
Andrew1
Blake1
Dave1
Evan1
Matt1
Nick 
Todd 
Zack 

전체 데이터의 중간쯤 되는 Matt와 먼저 비교를 해본다. Z와 비교해보았을 때 M은 더 앞에 있는 알파벳이므로 절반의 데이터를 소거할 수 있다. 그러면 이제 남은 데이터로 다시 비교를 해보자.

name탐색순서
Andrew1
Blake1
Dave1
Evan1
Matt1
Nick2
Todd2
Zack 

남은 데이터의 중간인 Tood와 비교를 해보았다. Z와 비교해보았을 때 T 역시 더 앞에 있는 알파벳이므로 절반의 데이터를 소거한다. 그러면 이제 남은 데이터는 Zack 뿐이다.

name탐색순서
Andrew1
Blake1
Dave1
Evan1
Matt1
Nick2
Todd2
Zack3

Zack은 언제나 동일하게 테이블상의 가장 마지막에 존재했지만, 인덱스 페이지에서는 3번만에 Zack을 탐색할 수 있었다.

참고

  • 코딩 시그널, 클러스터 인덱스와 넌클러스터 인덱스/ 개념 총정리, https://junghn.tistory.com/entry/DB-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EC%99%80-%EB%84%8C%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EA%B0%9C%EB%85%90-%EC%B4%9D%EC%A0%95%EB%A6%AC

  • 웨지의 개발 블록, Mysql 인덱스 - 클러스티드 인덱스와 논클러스티드 인덱스 개념편 , https://sihyung92.oopy.io/database/mysql-index

  • MySQL, Clustered and Secondary Indexes, https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html

  • DEV_GOLF, 클러스터링 인덱스 vs 논 클러스터링 인덱스, https://golf-dev.tistory.com/67

  • dataschool, Indexing, https://dataschool.com/sql-optimization/how-indexing-works/

This post is licensed under CC BY 4.0 by the author.

© . Some rights reserved.

Using the Jekyll theme Chirpy