[MySQL] 클러스터드 인덱스와 private key가 존재하지 않는 테이블

Y_Sevin·2024년 4월 30일
0

😅 필자가 개인적으로 공부하고 남기는 것이기 때문에 정보가 미흡할 수 있습니다. 잘못된 내용이나 추천해주실 방법이 있을경우 댓글 남겨주신다면 감사히 받겠습니다.

일반적으로 Private key가 없는 테이블을 생성하지는 않겠지만, MySQL은 유연성을 위해 Private key가 없는 테이블 생성을 허용하고 있다.

필자는 Private key가 없다면 오히려 성능만 낮아지고 이점이 별로 없을꺼 같은데 왜 MySQL은 이를 허용했는지 의문이였다.🤔 (물론 유연성이라는 이점은 있지만 이것만 있지는 않겠지..! 라는 생각을 했다.)

때문에 Private key가 없는 테이블에대해 찾아보던 중 테이블을 생성할 때 Private key가 없더라도 클러스터드 인덱스를 내부적으로 생성한다는 사실을 알게되었다.

클러스터드 인덱스

데이터베이스 테이블의 행을 키 값에 따라 정렬하는 인덱스이다.
클러스터드 인덱스는 인덱스의 순서와 동일하게 디스크의 물리적인 순서를 유지하기 때문에 빠른 탐색이 가능하다. 때문에 InnoDB에선 Private key를 생성하면 자동적으로 Private key로 클러스터드 인덱스가 생성된다.

Private Key로 클러스터드 인덱스가 생성되어 pk가 존재해야만 클러스터드 인덱스가 생성되는 것으로 오해하고 있었다....

PK가 없는 테이블

PK가 없는 테이블는 아래와 같이 두가지로 분리할 수 있다.

  1. Unique 인덱스가 존재하는 테이블
  2. Unique 인덱스, Private key 모두 없는 테이블

위와같이 분리한 이유는 클러스터드 인덱스를 생성하는 내부적인 동작방식의 차이가 있기 때문이다.
Uk가 존재하는 테이블은 테이블을 생성하는 시점에 Unique 인덱스 를 생성한다. 때문에 InnoDB는 테이블에 정의된 첫 번째 Unique인덱스를 찾고, 이를 클러스터드 인덱스로 사용한다.

사실 최적화를 생각한다면 당연한 얘기이다. pk가 없으니 구분가능한 uk를 찾고 해당 인덱스를 기반으로 클러스터드 인덱스를 생성한다면 빨라지니 말이다.

하지만 2번처럼 Unique 인덱스, Private key 모두 없는 테이블은 각 행을 구분할 수 있는 값이 존재하지 않는다. 그렇다면 클러스터드 인덱스를 어떻게 생성할까?

사실 InnoDB에는 테이블의 각 행마다 행 ID 값을 포함하는 가상의 컬럼이 존재한다. 이 행 ID 값은 6바이트로 구성되어있고 새로운 행이 삽입될 때마다 순차적으로 증가되도록 구현되어있다.
때문에 테이블에 Private key나 적절한 Unique 인덱스가 정의되어있지 않다면, 행 ID값을 사용해 "GEN_CLUST_INDEX"라는 클러스터드 인덱스를 생성한다.

MySQL docs를 살펴보면 아래와 같이 나와있다.

https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html

왜 생성할까..?

필자는 클러스터드 인덱스를 무조건 생성해주는 이유가 무엇일지 고민해보았다.
먼저 PK,UK가 존재하는 경우 해당 컬럼을 통해 행에 접근할 수 있으니 속도 측면에서 이점이 발생한다.
하지만 PK가 없는 테이블은 조건 탐색이 없는 Where절을 사용하지 않는 테이블일텐데 어떤 이득이 있을까?

사실 이 고민은 클러스터드 인덱스의 장점을 생각하지 않은 고민이였다...ㅎ
클러스터드 인덱스는 데이터가 물리적으로 정렬되어있다.
때문에 전체탐색을 주로 진행하는 테이블의 경우 데이터에 순차적으로 액세스할 수 있으니 탐색속도가 빨라지게 된다.
https://stackoverflow.com/questions/18764/whats-the-difference-between-a-table-scan-and-a-clustered-index-scan

결론

MySQL의 InnoDB엔진의 클러스터드 인덱스는 PK가 없더라도 모든 테이블에 생성된다~! 😅

profile
매일은 아니더라도 꾸준히 올리자는 마음으로 시작하는 개발블로그😎

0개의 댓글