백은빈, 이성욱 님의 "Real MySQL" 책을 정리한 포스팅 입니다.
1. 클러스터링 인덱스
- 프라이머리 키 값을 기준으로 정렬하여 저장하는 방식
- InnoDB 에서는 테이블 자체가 클러스터링 인덱스 구조로 관리됨 (InnoDB 전용 기능)
B+Tree 자료구조
레코드 저장 방식
- 클러스터링 인덱스는 인덱스 알고리즘이 아니라 테이블의 저장 방식임
- 테이블 자체가 프라이머리 키를 기준으로 정렬된 하나의 거대한 인덱스 구조로 관리됨
- 프라이머리 키 값 기준 가까운 레코드들이 물리적으로 인접하여 저장됨
프라이머리 키를 기준으로 레코드가 묶여서 저장됨
- 범위 검색이나 프라이머리 키 기반 조회가 매우 빠름
쓰기 성능 고려
- 프라이머리 키 순서대로 입력하면 성능이 좋음
- 키 값이 변경되면 물리적으로 리프 노드의 위치가 변할 수 있음
장점
- 프라이머리 키로 검색할 때 처리 성능이 매우 빠름
- 모든 세컨더리 인덱스가 프라이머리 인덱스를 가지므로 인덱스만으로 처리될 수 있는 경우가 많음
단점
용량
- 클러스터링 키 값의 크기가 클 경우 전체적으로 인덱스 크기가 커짐
성능
- 세컨더리 인덱스를 통해 검색할 때 프라이머리 키로 다시 한번 검색해야 하므로 성능이 느림
- INSERT할 때 프라이머리 키에 의해 레코드의 저장 위치가 결정되기 때문에 처리 성능이 느림
- 프라이머리 키를 변경할 때 레코드를 DELETE하고 INSERT하는 작업이 필요하기 때문에 처리 성능이 느림
vs 세컨더리 인덱스
- 기준 컬럼은 일반 컬럼이 아닌 프라이머리 키
- 리프 노드의 value값이 ROWID가 아닌 레코드의 모든 컬럼 값이 기록됨
프라이머리 키가 없는 InnoDB 테이블에서 클러스터링 테이블을 구성하는 방법
- 프라이머리 키가 있으면 기본적으로 프라이머리 키를 클러스터링 키로 선택
- NOT NULL 옵션의 유니크 인덱스 중에서 첫 번째 인덱스를 클러스터링 키로 선택
- 자동으로 유니크한 값을 가지도록 증가하는 칼럼(row_id) 을 내부적으로 추가한 후, 클러스터링 키로 선택
2. 세컨더리 인덱스에 미치는 영향
- 클러스터링 키 값이 변경될 때마다 레코드의 주소가 변경되고 그때마다 모든 인덱스에 저장된 주솟값을 변경해야 함
- 이런 오버헤드를 제거하기 위해 InnoDB 테이블(클러스터링 테이블)의 모든 세컨더리 인덱스는 해당 레코드가 저장된 주소가 아니라 프라이머리 키 값을 저장하도록 구현되어 있음
- 이로 인해 성능 저하를 우려하지 않아도 됨
3. 주의사항
설정
클러스터링 테이블의 경우, 모든 세컨더리 인덱스가 프라이머리 키를 포함함
- 레코드 건수가 커질수록 인덱스 크기가 크게 증가하므로 프라이머리 키를 신중하게 선택해야 함
프라이머리 키는 반드시 명시하기
- 프라이머리 키를 명시적으로 정의하지 않으면, InnoDB 스토리지 엔진이 내부적으로 일련번호 칼럼을 추가함
- 즉, AUTO_INCREMENT 컬럼을 생성하고 프라이머리 키로 설정하는 것과 같음
- 또한 ROW 기반의 복제나 InnoDB CLuster에서 프라이머리 키를 가져야만 정상적인 복제 성능을 보장함
성능
프라이머리 키는 AUTO-INCREMENT보다는 업무적인 칼럼으로 생성하기
- 프라이머리 키가 클러스터링 키로 사용되며, 레코드의 위치가 결정됨
- 프라이머리 키로 검색하는 경우 매우 빠르게 처리될 수 있음
- 이 성질을 이용하면 성능상 이점을 얻을 수 있음
인조 식별자 사용 (AUTO-INCREMENT)
- 세컨더리 인덱스도 필요하고 프라이머리 키의 길이도 길 경우
- 세컨더리 인덱스에 프라이머리 키가 포함되므로, 길이가 길면 성능이 낮아짐
- 조회보다는 INSERT 위주의 테이블
- ex) 로그 테이블
'Database > Mysql' 카테고리의 다른 글
[Real MySQL] 8-7. 인덱스: 멀티 밸류 인덱스 (0) | 2024.09.07 |
---|---|
[Real MySQL] 8-6. 인덱스: 함수 기반 인덱스 (0) | 2024.09.07 |
[Real MySQL] 8-9. 인덱스: 유니크 인덱스 (0) | 2024.09.07 |
[Real MySQL] 5-2. 트랜잭션과 잠금: 격리 수준 (0) | 2024.08.10 |
[Real MySQL] 15-4. 데이터 타입: JSON (0) | 2023.11.26 |