개발을 진행할 때 데이터베이스의 인덱스나 조인(Nested Loop Join 등)에 대한 내용을 자주 다루지 않아서 매번 필요할때 다시 찾아보고 있습니다. 또 까먹겠지만 다음에 조금 더 빨리 찾아볼 수 있도록 해당 내용을 정리합니다.
아래 내용은 책이나 문서를 보며 아는 대로 정리한 부분이라 잘못된 부분이 있을 수 있습니다. 대부분의 내용은 MySQL을 기준으로 합니다.
데이터베이스에서는 테이블의 데이터 검색 속도를 향상시켜주기 위해서 인덱스라는 개념을 제공하고 있습니다. 인덱스는 컬럼 단위로 생성되며, 아래와 같이 하나의 컬럼 혹은 여러개의 컬럼에 하나의 인덱스를 생성할 수 있습니다.
ALTER TABLE user ADD INDEX IDX_CLOSED_AT (closed_at);
ALTER TABLE user ADD INDEX IDX_CREATED_AT_AND_LAST_MOD_AT (created_at, last_modified_at);
별도로 인덱스를 만들지 않더라도 아래의 경우 자동으로 인덱스가 생성됩니다.
- Primary Key를 지정하는 경우 Clustered Index 생성
- Unique 제약 조건 지정 시 Non Clustered Index 생성
인덱스는 Clustered Index, Non Clustered Index 두가지가 존재하며 각각에 대해서는 아래에서 설명합니다.
Clustered Index
MySQL의 InnoDB 엔진에서는 B-Tree 기반 Clustered Index를 제공합니다.
Clustered Index를 기준으로 테이블 데이터를 물리적으로 재배열 하기 때문에 테이블 당 하나만 존재할 수 있습니다.
Clustered Index의 Leaf Node에는 실제 Row 데이터가 저장됩니다. 물리적으로 정렬되어 있어 Clustered Index 사용 시 검색 속도가 빠릅니다. 정렬되지 않은 데이터를 적재할 경우 성능의 저하가 일어날 수 있으므로 Primary Key의 경우 Auto Increment와 같이 정렬 순서를 보장하는 편이 좋습니다.
Non Clustered Index
Clustered Index와 달리 하나의 테이블에 여러 Non Clustered Index를 생성할 수 있습니다.
Non Clustered Index의 Leaf Node에는 Clustered Index의 키가 포함됩니다. 자세한 내용은 살펴보지 않았지만 아래와 같이 Non Clustered Index를 이용해 검색이 일어나는 경우 아래와 같이 Non Clustered Index의 Leaf Node를 찾은 뒤 Clustered Index를 활용해 데이터를 조회하는 것 같습니다.
인덱스는 검색 성능 향상을 위해 사용하지만, 테이블 내에 인덱스가 너무 많이 생성된 경우에는 DML 작업의 성능 저하가 일어날 수 있으므로 꼭 필요한 경우에만 인덱스를 추가하는것이 좋습니다.
Reference
https://www.sqlservercentral.com/articles/nonclustered-index-structure