[DB] Clustered / Non-Clustered Index

2022. 5. 31. 17:20[ Basic ]/# 데이터베이스

데이터베이스에 인덱스가 없다면 테이블에 데이터가 삽입되는 순서는 특정 제약이 없다. 또한 데이터 조회 시(일반적인 where절 사용) 테이블 풀스캔이 발생한다. 이때 match 되는 데이터를 찾더라도 데이터 순회를 끝내는 것이 아니라, 테이블의 끝까지 데이터를 '순차 탐색'하면서 match 되는 데이터를 '모두' 찾는다. 이러한 테이블 풀스캔이 항상 나쁘다고 할 순 없지만 데이터가 많아질수록 성능에 문제가 발생할 것이다. 

 

 

물리적으로는 한 테이블의 데이터 record들이 위와 같은 페이지 구조로 저장된다. 만약 record들을 특정 컬럼 기준으로 정렬해서 저장한다고 하면 테이블 풀스캔을 하지 않고도 찾고자 하는 데이터를 찾을 순 있지만 순차 탐색을 해야 한다는 단점이 존재한다.

 

이를 해결하기 위한 가장 대표적인 방법은 인덱스이다. 인덱스라는 단어 자체에 '정렬'이라는 키워드가 포함된다는 것을 반드시 기억해야 한다. 인덱스는 이진 탐색 트리이면서 balanced인 B-Tree(B+Tree)로 구성되어 있기 때문이다. 

 

 

 

 

Clustered Index

 

 

 

Clustered Index는 테이블 상의 row들이 물리적으로 정렬되어 있고 이들의 페이지를 인덱싱하는 기법이다. 데이터베이스 엔진은 테이블 상의 페이지를 참조하는 형태로 인덱스 페이지를 만들고 인덱스를 구성한다. 특정 데이터를 찾을 때 index tree를 탐색하며 데이터를 찾는다. 만약 중복 데이터를 갖는다면 이에 대한 정보도 인덱스에 저장한다. (중복 데이터의 범위)

 

Clustered Index의 단점은 새로운 데이터가 삽입될 때 실제 물리적인 테이블 상에서도 해당하는 위치에 데이터가 삽입되어야 한다는 것이다.

 

cf. Clustered Index는 테이블 하나 당 한 개만 존재할 수 있다.

Clustered Index는 테이블 데이터 자체를 포함하기 때문에 하나의 Clustered Index만 생성할 수 있다. 동일한 데이터를 물리적으로 다른 두 가지 방식으로 저장하는 것은 이를 또 다른 방법으로 정렬하기 위한 과정이 필요하다. 이와 반대로, 테이블 하나에 대해 여러 가지 다른 구조의 인덱스(다른 정렬 방식)를 만들기 위해서는 Non-Clustered Index를 활용해야 한다.

 

 

 

Non-Clustered Index

 

Non-Clustered Index는 테이블 상의 데이터(무작위적인 상태로 정렬되지 않은 형태)를 참조하는 포인터(RID; row identifiers)가 키 값으로 존재한다. 따라서 인덱스의 구조는 실제 테이블에 저장된 데이터의 row와 '독립적'으로 구성된다. 

 

Non-Clustered Index를 구성하기 위해서는 테이블 상의 데이터를 만들려는 인덱스의 정렬 방식으로 재구성해서 인덱스 페이지를 먼저 만든 후, (그림 상에서 아래서 두 번째 레이어) 트리 구조를 만들며 인덱스를 구성하는 과정을 거친다. 따라서 Non-Clustered Index를 구성할 때에는 정렬 기준을 명시해서 인덱스 키 순서를 구성해야 한다.

 

 

장점

- 하나의 테이블에 대한 다양한 정렬 방식으로 인덱스를 여러 개 정의할 수 있다.

- 실질적인 데이터를 삽입할 때 정렬을 고려하지 않아도 된다.(인덱스에 저장할 때에는 고려해야 함)

- 테이블 데이터의 참조값을 인덱스 키로 가지기 때문에 테이블 데이터가 unique하지 않더라도 인덱스 상에서는 unique 하게 저장할 수 있다.

- 새로운 정렬 기준을 기반으로 인덱스를 생성하기 때문에 필터링된 인덱스를 제공할 수 있다. 예를 들어 모든 데이터를 인덱스로 구성하지 않고 age라는 컬럼 값이 10보다 큰 데이터에 대해서만 인덱스를 구성할 수도 있다는 것이다. Clustered Index의 경우 테이블의 모든 데이터를 포함해야 하므로 필터링할 수 없다.

- Non-Clustered Index를 생성할 때 정렬 기준에 포함되지 않는 컬럼을 인덱스 트리의 리프 레벨에 추가할 수도 있다. 이 경우에는 실제 테이블의 데이터까지 참조하지 않고도 인덱스만으로 데이터를 조회할 수 있음을 의미한다. Clustered Index는 리프 레벨에 모든 컬럼을 사용할 수 있기 때문에 이러한 기능(include) 자체가 필요 없다.

 

 

 


 

결론

- Clustered Index는 테이블 자체의 모든 데이터를 표현하는 방법으로 테이블의 정렬 기준을 그대로 차용한다. 따라서 테이블 당 하나만 존재할 수 있다.

- Non-Clustered Index는 테이블 데이터를 참조하는, 물리적으로 별도의 구조(정렬 기준, 범위 등)를 자체적으로 생성하는 방법이기 때문에 테이블과 다른 정렬 기준을 가질 수 있으며 테이블 당 여러개 구성할 수 있다.

 

 

참고

- PK 제약조건은 Clustered Index를 생성하고 Unique 제약조건은 Non-Clustered Index을 생성한다.

- 제약조건과 이를 뒷받침하는 인덱스는 서로 다른 구성이며 뒷단에서 생성되는 인덱스 유형이다.