카디널리티(Cardinality)
카디널리티(Cardinality)는 데이터베이스의 특정 컬럼(열)이나 테이블에서 값의 다양성을 나타내는 지표이다. 카디널리티는 데이터베이스의 성능 최적화, 특히 쿼리 플랜의 결정 및 인덱스 구조의 설계에 중요한 역할을 한다.
컬럼 카디널리티 (Column Cardinality)
컬럼 카디널리티는 테이블의 특정 컬럼에 있는 서로 다른 값의 수를 의미한다. 컬럼의 카디널리티가 높다는 것은 그 컬럼이 많은 유니크한 값을 가지고 있다는 것을 의미하며, 카디널리티가 낮다는 것은 값의 중복이 많다는 것을 의미한다. 컬럼 카디널리티는 크게 세 가지 유형으로 분류된다.
- 높은 카디널리티(High Cardinality): 각 행이 고유한 값을 가지는 경우 (예: 사용자 ID, 이메일 주소)
- 중간 카디널리티(Medium Cardinality): 반복되는 값이 일부 있지만, 여전히 상당한 수의 고유한 값이 있는 경우 (예: 도시 이름, 제품 카테고리)
- 낮은 카디널리티(Low Cardinality): 값의 중복이 많은 경우 (예: 성별, 결혼 여부)
관계 카디널리티 (Relationship Cardinality)
관계 카디널리티는 데이터베이스 테이블 간 관계의 특성을 나타낸다. 주로 데이터 모델링의 맥락에서 사용되며, 테이블 간의 관계가 어떻게 형성되는지를 설명한다. 기본적으로 네 가지 유형이 있다.
- 일대일 (One-to-One): 한 테이블의 한 행이 관련 테이블의 정확히 한 행과 연결된다.
- 일대다 (One-to-Many): 한 테이블의 한 행이 관련 테이블의 여러 행과 연결될 수 있다.
- 다대일 (Many-to-One): 여러 행이 관련 테이블의 한 행과 연결된다.
- 다대다 (Many-to-Many): 한 테이블의 여러 행이 관련 테이블의 여러 행과 연결될 수 있다.
카디널리티는 쿼리 성능을 이해하고 최적화하는 데 매우 중요하다. 예를 들어, 높은 카디널리티를 가진 컬럼에 인덱스를 생성하면 쿼리 성능이 크게 향상될 수 있지만, 낮은 카디널리티를 가진 컬럼에 인덱스를 생성하면 오히려 성능이 저하될 수 있다. 따라서 데이터베이스 설계와 쿼리 작성 시 카디널리티를 고려하는 것이 중요하다.
낮은 카디널리티를 가진 칼럼에 인덱스 생성하면 왜 성능이 저하될까? ❗️
인덱스 스캔 비효율성: 낮은 카디널리티의 컬럼에 대한 쿼리는 데이터 대부분을 반환하게 된다. 인덱스는 유니크한 값에 빠르게 접근하기 위해 설계되었지만, 만약 대부분 행이 인덱스를 통해 선택된다면, 인덱스를 사용하는 것이 전체 테이블을 스캔하는 것보다 더 많은 I/O를 발생시킬 수 있다.
인덱스 유지 관리 비용: 인덱스는 데이터가 변경될 때마다 업데이트되어야 한다. 삽입, 삭제, 업데이트 작업이 일어날 때마다 인덱스도 변경되어야 하므로, 낮은 카디널리티의 컬럼에 인덱스를 생성하면, 이러한 유지 관리 작업으로 인한 오버헤드가 성능에 부정적인 영향을 미칠 수 있다.
캐시 사용의 비효율성: 데이터베이스는 자주 사용되는 데이터를 메모리에 캐시하여 빠르게 액세스할 수 있게 한다. 낮은 카디널리티 인덱스는 대량의 데이터를 반환할 가능성이 높기 때문에, 캐시 메모리를 비효율적으로 사용하게 할 수 있다.
인덱스 vs 전체 테이블 스캔 ❗️
인덱스 사용이 전체 테이블 스캔에 비해 더 많은 I/O를 발생시킬 수 있는 이유는 인덱스 스캔과 데이터 검색 과정에서 발생하는 “추가적인 접근 단계” 때문이다.
- 인덱스 접근 방식
- 쿼리가 실행되면, 먼저 인덱스를 사용하여 해당하는 키 값을 찾는다. 이 과정에서 인덱스 구조(보통 B-tree)를 탐색하여 일치하는 키 값을 찾는 I/O 작업이 발생한다.
- 인덱스에서 키 값에 해당하는 항목을 찾으면, 그 항목이 가리키는 실제 데이터 행의 위치를 알게 된다. 그런 다음 데이터베이스는 이 위치 정보를 사용하여 실제 테이블에서 데이터를 읽어야 한다.
- 낮은 카디널리티를 가진 컬럼에 대한 쿼리는 데이터 대부분을 반환하게 된다. 이 경우, 인덱스를 통해 많은 수의 행을 찾게 되므로, 실제 테이블에서 이 행들을 읽어오기 위한 랜덤 액세스가 많이 발생한다. 랜덤 액세스는 순차적 액세스보다 훨씬 더 많은 시간과 I/O를 요구한다.
결론적으로, 낮은 카디널리티 인덱스는 많은 수의 랜덤 액세스를 발생시켜 전체 테이블 스캔을 수행하는 것보다 더 많은 I/O 작업을 유발할 수 있다. 따라서 낮은 카디널리티의 컬럼에 대해서는 인덱스 사용은 성능 향상을 가져오지 못한다. 🫢