•
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 칼럼을 추가하고 이를 프라이머리 키로 설정하면 된다.