Search
Duplicate
8️⃣

클러스터링 인덱스

MySQL 서버에서 클러스터링은 테이블의 레코드를 비슷한 것들끼리 묶어서 저장하는 형태로 구현, 이는 주로 비슷한 값들을 동시에 조회하는 경우가 많다는 점에서 착안되었다.
MySQL 클러스터링 인덱스는 InnoDB 스토리지 엔진에서만 지원하며 나머지는 지원하지 않는다.

1. 클러스터링 인덱스

클러스터링 인덱스는 테이블의 프라이머리 키에 대해서만 적용된다.
즉 프라이머리 키 값이 비슷한 레코드끼리 묶어서 저장하는 것, 여기서 중요한것은 프라이머리 키 값에 의해 레코드 저장 위치가 결정된다는 것이다.
프라이머리 키 값이 변경되면 해당 레코드의 물리적인 위치가 변경되야 하므로 프라이머리 키를 신중하게 결정해야 한다.
클러스터링 인덱스는 프라이머리 키 값에 의해 레코드의 저장 위치가 결정되므로 인덱스 알고리즘이라기보단 테이블 레코드의 저장 방식이다.
또한 클러스터링의 기준이되는 프라이머리 키는 클러스터링 키라고도 표현하며 일반적으로 InnoDB와 같이 항상 클러스터링 인덱스로 저장되는 테이블은 프라이머리 키 기반의 검색이 매우 빠르며 저장이나 변경은 상대적으로 느리다.
B-Tree 인덱스도 인덱스 키 값으로 이미 정렬되어 저장, 이는 어떻게 보면 인덱스의 키 값으로 클러스터링된 것으로 생각할 수 있는데, 이는 클러스터링 인덱스라고 부르지 않는다.
테이블의 레코드가 프라이머리 키 값으로 정렬되어 저장된 경우만 클러스터링 인덱스 또는 클러스터링 테이블이라고 한다.
만약 프라이머리 키가 없는 InnoDB 테이블은 어떻게 클러스터링 테이블로 구성할까?
1.
프라이머리 키가 있으면 기본적으로 프라이머리 키를 클러스터링 키로 선택한다.
2.
없는 경우, NOT NULL 옵션의 유니크 인덱스 중에서 첫 번째 인덱스를 클러스터링 키로 선택한다.
3.
이 역시 없는 경우, 자동으로 유니크한 값을 가지도록 증가되는 칼럼을 내부적으로 추가한 후, 클러스터링 키로 선택한다.
가급적이면 클러스터링 인덱스는 테이블 당 하나만 가질 수 있는 엄청난 혜택이므로 명시적으로 생성해두는 것이 좋다.

2. 세컨더리 인덱스에 미치는 영향

MyISAM이나 MEMORY 스토리지 엔진의 클러스터링되지 않는 테이블은 INSERT된 공간에서 변경되지 않는다.
그러나 InnoDB의 세컨더리 인덱스가 실제 레코드가 저장된 주소를 가지고 있다면 클러스터링 키 값이 변경될 때마다 데이터 레코드의 주소가 변경되고 해당 주솟값을 변경해주어야 한다.
이런 불필요한 오버헤드를 줄이기 위해 InnoDB 테이블은 모든 세컨더리 인덱스를 해당 레코드가 저장된 주소가 아닌 프라이머리 키 값을 저장하도록 구현되어 있다.

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

장점
프라이머리 키로 검색할 때 처리 성능이 매우 빠르다.
테이블의 모든 세컨더리 인덱스가 프라이머리 키를 가지고 있기 때문에 인덱스만으로 처리될 수 있는 경우가 많다.
단점
테이블의 모든 세컨더리 인덱스가 클러스터링 키를 갖기 때문에 클러스터링 키 값의 크기가 클 경우 전체적으로 인덱스의 크기가 커진다.
세컨더리 인덱스를 통해 검색할 때 프라이머리 키로 다시 한번 검색해야 하므로 처리 성능이 느리다.
INSERT할 때 프라이머리 키에 의해 레코드의 저장 위치가 결정되기 때문에 처리 성능이 느리다.
프라이머리 키를 변경할 때 레코드를 삭제하고 삽입하는 작업이 필요하기 때문에 처리 성능이 느리다.
대체로 클러스터링 인덱스의 장점은 빠른 읽기이며 단점은 느린 CUD이다.
일반적으로 웹 서비스와 같은 온라인 트랜잭션 환경에서는 쓰기와 읽기 비율이 1:9, 2:8이기 때문에 조금 느린 쓰기를 감수하고도 읽기를 빠르게 유지하는 것이 중요하다.

4. 클러스터링 테이블 사용 시 주의사항

MyISAM과 같이 클러스터링되지 않은 테이블에 비해 InnoDB 테이블에서는 조금 더 주의해야할 부분이 존재한다.
1.
클러스터링 인덱스 키의 크기
클러스터링 테이블의 경우 모든 세컨더리 인덱스가 프라이머리 키 값을 포함하므로 프라이머리 키의 크기가 커지면 세컨더리 인덱스도 자동으로 크기가 커진다.
인덱스가 커지면 커질수록 같은 성능을 내기 위해 버퍼 풀에 적재되어야 하므로 메모리 관련 이슈가 생길 수 있으니 신중하게 선택해야 한다.
2.
프라이머리 키는 가급적 AUTO-INCREMENT보다는 비즈니스적으로 의미가 있는 칼럼으로 생성한다.
InnoDB의 프라이머리 키는 클러스터링 키로 사용되며 이 값에 의해 레코드 위치가 결정된다.
즉 프라이머리 키로 검색하는 경우 클러스터링되지 않은 테이블에 비해 매우 빠르게 처리될 수 있다.
이는 InnoDB에서 큰 차이를 만들어내기 때문에 검색에서 빈번히 사용되므로 설령 그 칼럼의 크기가 크더라도 업무적으로 해당 레코드를 대표할 수 있다면 해당 칼럼을 프라이머리 키로 설정하는 것이 좋다.
3.
프라이머리 키는 반드시 명시할 것
프라이머리 키가 없는 테이블이 존재하는데, 가능하면 AUTO_INCREMENT 칼럼을 이용해서라도 프라이머리 키를 생성하는 것을 권장한다.
InnoDB 테이블에서 프라이머리 키를 정의하지 않으면 InnoDB 스토리지 엔진이 내부적으로 일련번호 칼럼을 추가하므로 결과적으론 AUTO_INCREMENT 칼럼을 추가하는 것과 똑같다.
다만 접근이 불가능하므로 생성하는 것을 권장한다.
4.
AUTO-INCREMENT 칼럼을 인조 식별자로 사용할 경우
여러 개의 칼럼의 복합으로 프라이머리 키가 만들어지는 경우 프라이머리 키의 크기가 길어질 때가 가끔 있다.
프라이머리 키의 크기가 길어도 세컨더리 인덱스가 필요치 않다면 그대로 프라이머리 키를 사용하는 것이 좋다.
세컨더리 인덱스도 필요하고 프라이머리 키의 크기도 길다면 AUTO_INCREMENT 칼럼을 추가하고 이를 프라이머리 키로 설정하면 된다.