본문 바로가기

카테고리 없음

[Real MySQL] 8. 인덱스 - 클러스터링 인덱스

클러스터링 인덱스(클러스터링 테이블)

  • 클러스터링 인덱스는 테이블의 PK에 대해서 적용되는 내용이다. 즉 PK 값이 비슷한 레코드끼리 묶어서 저장하는 것을 클러스터링 인덱스라고 표현한다. 참고로 MySQL에서 클러스터링 인덱스는 InnoDB 스토리지 엔진에서 디폴트로 설정된다.
  • 클러스터링 인덱스, 즉 PK 값에 의해 레코드의 저장 위치가 결정된다. 따라서 PK 값이 바뀌면 그 레코드의 물리적 저장 위치가 바뀌어야 한다. 즉, PK 값으로 클러스터링된 테이블은 PK 값에 대한 의존도가 크기 때문에 신중히 PK 값을 설정해야 한다.
  • 클러스터링 인덱스는 PK 값에 의해 레코드의 저장 위치가 결정되므로 사실 인덱스 알고리즘이라기보다 테이블 레코드의 저장 방식이라고 볼 수 있다. 그래서 "클러스터링 인덱스"와 "클러스터링 테이블"은 동의어로 사용되기도 한다. 또한 클러스터링의 기준이 되는 PK는 클러스터링 키라고도 표현한다.
  • 한 테이블 당 클러스터링 인덱스는 단 하나만 가질 수 있다.
  • 일반적으로 InnoDB와 같이 항상 클러스터링 인덱스로 저장되는 테이블은 PK를 기반으로 인덱스가 생성되어 있으므로, PK 기반의 검색이 매우 빠르다. 대신 레코드 저장이나 PK 값의 변경은 상대적으로 느리다. 

PK가 없는 테이블의 클러스터링 테이블

InnoDB는 PK를 기준으로 클러스터링 인덱스를 생성한다. 그러면 PK가 없는 테이블의 경우에는 어떨까?

 

PK가 없으면 InnoDB 스토리지 엔진이 다음 우선순위대로 PK를 대체할 칼럼을 선택한다.

  1. PK가 있으면 기본적으로 PK를 클러스터링 키로 선택
  2. NOT NULL이면서 유니크 인덱스 중 첫 번째 인덱스를 클러스터링 키로 선택
  3. 유니크한 값을 가지도록 자동으로 증가하는 칼럼을 내부적으로 추가한 후 클러스터링 키로 선택

1, 2번 과정을 거쳤음에도 적절한 클러스터링 키 후보를 찾지 못하면, 내부적으로 레코드의 일련번호 칼럼을 생성한다. 이렇게 자동으로 추가된 PK(일련번호 칼럼)는 사용자에게 노출되지 않으며, 쿼리 문장에 명시적으로 사용할 수도 없다. 즉, PK나 유니크 인덱스가 전혀 없는 테이블의 경우, 아무 의미 없는 숫자로 클러스터링되며, 이는 우리에게 아무런 혜택도 주지 않는다. 

세컨더리 인덱스와 클러스터링 인덱스의 구조

다음 그림은 MyISAM 테이블의 인덱스와 데이터 레코드의 관계와 InnoDB 테이블의 인덱스와 데이터 레코드의 관계를 보여준다. 

두 스토리지 엔진의 인덱스에서 가장 큰 차이점은 세컨더리 인덱스를 통해 데이터 파일의 레코드를 찾아가는 방법에 있다(세컨더리 인덱스: 클러스터링 인덱스를 제외한 모든 인덱스).

  • MyISAM 테이블의 인덱스: 세컨더리 인덱스 구조의 리프 노드가 레코드의 물리적인 주소를 갖는다.
  • InnoDB 테이블의 인덱스: 세컨더리 인덱스 구조의 리프 노드가 레코드의 물리적인 주소가 아닌 PK 값을 갖는다. 그리고 PK 값을 통해 클러스터링 인덱스를 한 번 더 검색하여 실제 레코드를 찾는다.

클러스터링 인덱스의 장점과 단점

장점

  • PK를 기준으로 인덱스가 생성되어 있으므로, PK로 검색 시 처리 성능이 매우 빠르다.

단점

  • PK 값이 클수록 전반적인 인덱스 크기가 커진다. 세컨더리 인덱스가 리프 노드에서 클러스터링 키인 PK를 갖기 때문이다.
  • 세컨더리 인덱스로 검색할 때 성능이 느리다. 세컨더리 인덱스로 검색하면 리프 노드의 PK를 통해 한 번 더 클러스터링 인덱스를 검색해야 하기 때문이다.
  • INSERT 성능이 느리다. INSERT 시 PK 값을 기준으로 물리적 저장 위치를 결정하기 때문이다.
  • PK 값의 변경 성능이 느리다. PK 값을 변경하면 기존 PK에 따른 저장 위치에서 레코드를 DELETE하고 새로운 위치에 INSERT하기 때문이다.

정리하자면, 클러스터링 인덱스의 장점은 빠른 읽기(SELECT)이며, 단점은 느린 쓰기(INSERT, UPDATE, DELETE)이다. 일반적으로 웹 서비스와 같은 온라인 트랜잭션 환경에서는 쓰기와 읽기 비율이 2:8 또는 1:9 정도이기 때문에 느린 쓰기를 감수하고 빠른 읽기를 선택하기 때문에 클러스터링 인덱스의 이점을 누릴 수 있다.


Reference

  • 위키북스, Real MySQL 8.0