DB

클러스터링 인덱스 vs 논-클러스터링 인덱스

@xftg77g 2022. 10. 5. 00:59

인덱스의 기본 개념

인덱스는 책에 있는 색인과 같은 기능입니다.

 

 

어떤 책이 있다고 했을 때, 한라산이라는 단어가 나오는 페이지를 찾고 싶다면 색인을 이용해서 빠르게 찾을 수 있습니다. 인덱스도 데이터베이스에서 색인과 비슷한 역할을 수행합니다.

 

간략하게 인덱스를 사용함으로써 얻게 되는 장점과 단점을 작성해보겠습니다.

 

장점

  • 탐색 속도가 빨라질 수 있다.
    • 즉 시스템 전체의 성능 향상으로 이어질 수 있다.

단점

  • 색인처럼 인덱스를 위한 별도의 공간이 필요하므로 추가 메모리를 사용한다.
  • 인덱스를 작성할 시간이 필요하다.
  • 데이터의 변경 작업이 자주 일어난다면 인덱스 수정으로 인해 성능이 나빠질 수 있다.

 

인덱스는 두 가지 종류가 있습니다.

  1. 클러스터링 인덱스
  2. 논-클러스터링 인덱스 (or 보조 인덱스)

 

클러스터링 인덱스

 

위 그림을 보시면 RollNo 라는 인덱스를 확인하실 수 있습니다. 그리고 RollNo의 PageId를 따라가시면 리프 페이지에 데이터가 있는 것을 보실 수 있습니다. 즉 리프 페이지가 데이터 페이지이며, 데이터 페이지가 곧 데이터입니다. 굉장히 직관적입니다.

 

페이지를 살펴보시면 인덱스를 기준으로 정렬되어 있는 모습도 보실 수 있습니다. 이 때문에 클러스터링 인덱스는 범위 탐색에서 강력한 성능을 발휘합니다.

 

💡어려우신가요!
위 그림은 B-Tree 자료구조를 기반으로 합니다. 각 상자는 데이터베이스에서 페이지라고 하는 단위입니다. 페이지는 데이터베이스에서 저장되는 최소한의 단위입니다. MySQL은 기본 16Kbyte 크기의 페이지를 가진다고 합니다. 데이터를 한 개만 저장하려고 해도 무조건 하나의 페이지가 필요합니다.

 

생성

사실 기본키(PRIMARY KEY)는 클러스터링 인덱스를 생성합니다. 그래서 그런지 클러스터링 인덱스는 테이블 당 하나만 설정할 수 있다는 점도 기본키의 특성과 동일합니다. 그 외에도 NOT NULL UNIQUE 제약을 설정하면 해당 칼럼은 클러스터링 인덱스로 설정됩니다.

 

만약 PRIMARY KEY와 NOT NULL UNIQUE가 동시에 설정되면 PRIMARY KEY가 더 높은 우선순위를 가집니다.

 

논-클러스터링 인덱스

위 그림은 아까 클러스터링 인덱스에서 보았던 테이블과 동일한 테이블에서 논-클러스터링 인덱스를 적용한 예시입니다.

원래 그림이 이상해서 제가 임의로 수정했습니다..

보시면 이번에는 MobileNo 컬럼이 인덱스로 설정된 것을 볼 수 있습니다. PageId를 따라가시면 리프 페이지에서 다시 PageId+offset을 확인하실 수 있습니다. offset은 페이지에서의 행 번호라고 보시면 될 것 같습니다. 예를 들어 1000 + #1 이라는 것은 1000번 페이지에 첫 번째 행을 의미합니다.

 

데이터 페이지를 살펴보시면 인덱스의 순서에 관계 없이 데이터가 채워져 있는 것을 보실 수 있습니다. 클러스터링 인덱스의 경우 데이터 페이지가 모두 정렬되어 있어야 하지만 논-클러스터링 인덱스의 경우 그럴 필요가 없습니다.

 

💡 이 차이는 범위 탐색에서 유의미한 성능 차이를 만들어냅니다. 클러스터링 인덱스의 경우 데이터 페이지가 정렬되어 있기 때문에 범위 탐색에 매우 유리한 반면 (캐시의 공간적 지역성 이점도 얻을 수 있습니다) 논-클러스터링의 경우 범위 탐색에서 매우 불리한 것을 알 수 있습니다. 더 많은 페이지를 탐색해야 하기 때문입니다.

 

생성

기본 INDEX 생성, UNIQUE INDEX 생성, UNIQUE 제약, UNQIEU NULL 제약은 넌-클러스터링 인덱스를 생성합니다.

 

문제점

모든 인덱스는 INSERT 작업이 일어날 때 성능이 급격히 느려질 수 있다는 단점이 있습니다. INSERT 작업은 어쩔 수 없이 INDEX 수정 작업을 동반하고, 페이지가 모두 가득 찬 경우 페이지 분할 작업으로 인해 성능이 안 좋아질 수 있습니다. 다만 보편적으로 실제 비즈니스 환경에서 읽기 : 쓰기 작업은 8 : 2 정도의 비율이라고 하니 읽기 성능을 위해 쓰기 성능과 타협하는 것이 나쁜 방식은 아닙니다.