카디널리티란?
Index 설정 시 고려해보기
카디널리티 (Cardinality)
중복도가 “낮으면” 카디널리티가 “높다”라고 표현하고,
중복도가 “높으면” 카디널리티가 “낮다”라고 표현한다.
카디널리티는 전체 행에 대한 특정 컬럼의 중복 수치를 나타내는 지표이다.
한마디로 값에 중복이 많으면 카디널리티가 낮음
예를들어
주민등록번호 같은 경우 중복되는 값이 없으므로 카디널리티가 높다고 할 수 있다.
이름같은 경우에는 주민등록번호에 비해서 중복되는 값이 많으므로, 이름은 주민등록번호에 비해서 카디널리티가 낮다라고 할 수 있다.

위 테이블에서 ID는 중복되는 값이 없어서 unique하다. --> 카디널리티가 높다.
name의 경우에는 중복(distinct)값이 6건(kim, park, lee, choi, seol, yoon) 이므로 “id” 컬럼 보다는 카디널리티가 낮다.” 라고 얘기한다.
address는 distinct가 3건(seoul, incheon, daegu) 이므로 카디널리티가 “제일 낮다”.
distinct 값이 많다는건 중복도가 낮다는 의미이다.
id 컬럼은 distinct 값이 9이다.
user 테이블의 distinct를 보면 id(9건) > name(6건) > address(3건) 이다.
즉 distinct 값이 많으면 중복도가 낮다. = 카디널리티가 높다고 생각하면 된다.
즉, 카디널리티는 객관적 수치보다는 상대적인 개념으로 이해해야 한다.
인덱스를 걸 때, 내가 원하는 데이터를 선택하는 과정에서 최대한 많은 데이터가 걸러져야 성능이 좋을 것이다.
(선택하는 데이터가 많아질수록 Full Scan에 가까워지므로)
즉, 여러 컬럼을 동시에 인덱싱할 때, 카디널리티가 높은 컬럼(중복이 적은 컬럼)을 우선순위로 두는 것이 인덱싱 전략에 유리하다.
결론 : distinct 값이 높은 것은 카디널리티가 높다. --> 인덱스 우선순위가 될 수 있다.
예시
위에 예시로 사용했었던 User 테이블에 대해 두 개의 인덱스를 만들었다.
idx_address_first 라는 인덱스와 idx_id_first 라는 인덱스이다.
두 인덱스는 모두 세 개의 컬럼을 전부 인덱스 컬럼으로 사용했다.
전자의 경우 이름 그대로 address 컬럼을 가장 먼저 인덱스 컬럼으로 사용했고,
후자의 경우 id 컬럼을 가장 먼저 인덱스 컬럼으로 사용했다.
다시 말해서, 전자의 경우 카디널리티가 가장 낮은 컬럼(중복도가 높은 컬럼)을 우선적으로 인덱싱 했고,
후자의 경우 카디널리티가 높은 컬럼(중복도가 낮은 컬럼)을 우선적으로 인덱싱 했다.

❓단순히 인덱싱 컬럼의 순서를 바꾼 것이 실제 동작에서 어떤 차이를 가져올까?
쿼리를 통해 이해해보자.
세 번째 줄을 보면 'use index' 키워드를 사용하는데, 이를 사용하지 않으면 쿼리 실행 시 옵티마이저가 자동으로 인덱스를 생성한다.
본 쿼리에서는 idx_location_first와 idx_id_first 인덱스를 테스트하기 위해 use index 키워드를 사용해 명시적으로 인덱스를 지정해주었다.
우선, 카디널리티가 상대적으로 낮은 idx_location_first 인덱스를 가지고 테스트하면 location 컬럼을 우선적으로 인덱싱 할 것이다.
쿼리에서는 where절에 (id, name, location) 순서로 질의 했지만, location 컬럼에 우선적으로 인덱싱이 되어있으므로 내부적으로 location 컬럼을 먼저 탐색하게 된다.
즉, 먼저 인덱스에서 location이 'seoul'인 값을 거르므로, 해당하는 8개의 데이터가 남는다.
인덱싱하면 인덱스를 걸어뒀던 데이터만 남게된다.
다음으로 name이 'lee'인 데이터를 거르게 되는데, 남은 8개 데이터에 대해서만 확인하고 일치하는 데이터 3개가 남는다. 마지막으로 id가 '0'인 값을 거르기 위해서 3개 데이터에 대해 검색을 실시한다.
이번에는 idx_id_first 인덱스를 사용하면 어떻게 되는지 보자.
idx_id_first는 location에 비해 카디널리티가 더 높은 컬럼에 인덱스를 걸어준 경우이다.
idx_id_first 의 경우는 id 컬럼을 우선으로 인덱싱한다.
즉, 인덱스에서 id = '0'인 값을 거르므로 이미 첫 번째 검색에서 한 건의 데이터만 남는다.
다음으로 남은 한 건의 데이터에 대해서만 name = “lee”인지 여부를 확인하다.
마지막으로, 역시 남은 한 건의 데이터에 대해서만 location = “seoul” 인지 여부를 확인한다.
Summary
인덱스 컬럼을 선택할 때, 당연히 컬럼의 데이터 중복에 대한 고려는 필수일 것이고, 카디널리티는 그 중복도를 고려할 때 참고하는 용으로 사용하는 하나의 지표일 뿐이다.
Last updated