본문 바로가기
ComputerScience/RealMySQL

8.인덱스 - 클러스터링 인덱스

by 규난 2023. 1. 2.
728x90

이번 포스트에서는 MySQL InnoDB 스토리지 엔진의 클러스터링 인덱스에 대해서 알아보도록 하겠습니다.

 

클러스터링 인덱스

클러스터링이란 여러 개를 하나로 묶는다는 의미로 주로 사용됩니다.

MySQL 서버에서 클러스팅이란 테이블의 레코드를 비슷한 것(프라이머리 키를 기준으로)들 끼리 묶어서 저장하는 형태로 구현되는데, 이는 주로 비슷한 값들을 동시에 조회하는 경우가 많다는 점에서 착안되었고 MySQL에서는 InnoDB 스토리지 엔진에서만 지원합니다.

 

프라이머리 키 값이 비슷한 레코드끼리 묶어서 저장하기 때문에 프라이머리 키에 대해서만 적용됩니다.

여기서 중요한 것은 프라이머리 키 값에 의해 레코드의 저장 위치가 결정되고 프라이머리 키 값이 변경되면 레코드의 물리적인 저장 위치가 바뀌어야 한다는 것을 의미합니다. 따라서 프라이머리 키 값으로 클러스터링 된 테이블은 프라이머리 키에 대한 의존도가 상당히 크기 때문에 프라이머리 키 선정을 신중하게 해야합니다.

 

InnoDB 스토리지 엔진의 클러스터링 키 선택 기준은

  1. 프라이머리 키가 있으면 기본적으로 프라이머리 키를 클러스터링 키로 선택하고
  2. 없으면 NOT NULL 옵션의 유니키 인덱스 중 첫 번째 인덱스를 클러스터링 키로 선택하게 됩니다.
  3. 만약 둘 다 없을 경우에는 자동으로 유니크한 값을 가지도록 증가되는 컬럼을 내부적으로 추가한 후 클러스터링 키로 선택하게 되는데 이렇게 자동으로 추가된 프라이머리 키는 사용자에게 노출되지 않아서 쿼리 문장에 명시적으로 사용할 수 없게되어 클러스터링 인덱스가 가지는 장점을 이용할 수 없습니다. 그러니 가능하다면 꼭 프라이머리 키를 명시적으로 생성해주도록 합시다.

클러스터링 인덱스와 세컨더리 인덱스를 같이 사용하는 경우 세컨더리 인덱스의 리프 페이지에는 데이터 주소가 아닌 프라이머리 키의 값이 저장되는데 그 이유는 데이터의 주소(RID : 데이터 페이지와 그 페이지의 몇 번째 행에 데이터가 있는지를 나타내는 주소)를 저장하게 되면 데이터의 쓰기(삽입, 수정, 삭제)가 일어나게 되면 데이터가 정렬이 되어 데이터의 주소가 바뀌게 되고 데이터의 주소가 바뀌면 세컨더리 인덱스의 많은 페이지들도 저장한 데이터의 주소값을 변경해야 하는 현상이 발생하게 됩니다. 이런 오버헤드를 제거하기 위해 InnoDB 테이블은 데이터가 저장된 주소가 아니라 프라이머리 키의 값을 저장하도록 구현돼 있습니다.

 

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

  • 장점
    • 프라이머리 키(클러스터링 키)로 검색할 때 처리 성능이 매우 빠릅니다. (특히, 프라이머리 키를 범위 검색하는 경우)
    • 테이블의 모든 세컨터리 인덱스가 프라이머리 키를 가지고 있기 때문에 인덱스만으로 처리될 수 있는 경우가 많습니다. (커버링 인덱스)
  • 단점
    • 테이블의 모든 세컨더리 인덱스가 클러스터링 키를 갖기 때문에 클러스터링 키 값의 크기가 클 경우 전체적으로 인덱스의 크기가 커집니다.
    • 세컨더리 인덱스를 통해 검색할 때 프라이머리 키로 다시 한번 검색해야 하므로 처리 성능이 느릴 수 있습니다.
    • 데이터의 쓰기가 일어나는 경우 프라이머리 키에 의해 레코드의 저장 위치가 결정되기 때문에 처리 성능이 느립니다.
    • 프라이머리 키를 변경할 때 레코드를 DELETE하고 INSERT하는 작업이 필요하기 때문에 처리 성능이 느립니다
728x90