DB에는 여러 개의 테이블이 존재하고 그 테이블에는 다양한 수의 데이터가 쌓입니다. 만약 천 만개의 데이터가 쌓였다고 가정할 때, 여러 조건을 조합해서 데이터를 조회하려면 로딩 시간이 아주 오래 걸립니다. 이 때 인덱스(Index)를 설정하면 속도가 빨라집니다.
✅ 인덱스는 WHERE 절에서 효과가 있다.
인덱스는 SELECT
- FROM
- WHERE
절 중 WHERE
절에 사용할 컬럼에 대한 효율화라고 볼 수 있습니다. WHERE절을 사용하지 않고 인덱스가 걸린 컬럼을 조회하는 것은 성능에 아무런 영향이 없습니다.
예를 들어, '학생'
테이블에 '학번'
, '이름'
, '전화번호'
가 있다고 가정해봅시다.
인덱스는 '학번'
, '전화번호'
에 걸려 있습니다. 다음 중 인덱스가 영향을 주는 쿼리는 어떤 것일까요 ?
SELECT '학번' FROM '학생';
SELECT '전화번호' FROM '학생' WHERE '이름' = '김철수';
SELECT * FROM '학생' WHERE 학번' = 1;
정답은 3번입니다.
WHERE절에 사용할 때 성능을 향상시킵니다.
인덱스는 하나 혹은 여러 개의 컬럼에 대해 설정할 수 있습니다.
단일 인덱스를 여러 개 생성할 수도 여러 컬럼을 묶어 복합 인덱스를 설정할 수도 있습니다.
그러나 무조건 많이 설정하는게 검색 속도 향상을 높여주지는 않습니다.
인덱스는 데이터베이스 메모리를 사용하여 테이블 형태로 저장되므로 개수와 저장 공간은 비례합니다.
- 조회시 자주 사용하고
- 고유한 값 위주로
인덱스를 설정하는게 좋습니다.
SELECT 쿼리에서 성능이 잘 나오지만 INSERT
, UPDATE
, DELETE
쿼리에서는 때에 따라 다릅니다.
UPDATE
,DELETE
는 WHERE 절에 잘 설정된 인덱스로 조건을 붙여주면 조회할 때 성능은 크게 저하되지 않으나 (업데이트 할 데이터를 찾을 때의 속도가 빨라지는 것이지, 업데이트 자체가 빨라지는 것은 아님)- INSERT의 경우, 새로운 데이터가 추가되면서 기존에 인덱스 페이지에 저장되어 있던 탐색 위치가 수정되어야 하므로 효율이 좋지 않습니다.
인덱스는 한 테이블당 보통 3~5개 정도가 적당합니다.
물론 테이블의 목적 등에 따라 개수는 달라질 수 있습니다.
인덱스는 컬럼을 정해서 설정하는 것이므로 후보 컬럼의 특징을 잘 파악해야 합니다.
아래 4가지 기준을 사용하면 효율적으로 인덱스를 설정할 수 있습니다.
카디널리티 (Cardinality)
선택도 (Selectivity)
활용도
중복도
✅ 카디널리티가 높을 수록 인덱스 설정에 좋은 컬럼입니다.
즉, 한 컬럼이 갖고 있는 값의 중복 정도가 낮을 수록 인덱스로 사용하기 좋습니다.
컬럼에 사용되는 값의 다양성 정도, 즉 중복 수치를 나타내는 지표입니다.
후보 컬럼에 따라 상대적으로 중복 정도가 낮다, 혹은 높다로 표현됩니다.
예를 들어 10개 rows를 가지는 '학생'
테이블에 '학번'
과 '이름'
컬럼이 있다고 해봅시다.
'학번'
은 학생마다 부여 받으므로 10개 값 모두 고유합니다.- 중복 정도가 낮으므로 카디널리티가 높습니다.
'이름'
은 동명이인이 있을 수 있으니 1~10개 사이의 값을 가집니다.- 중복 정도가 '학번'에 비해 높으므로 카디널리티가 낮다고 표현할 수 있습니다.
✅ 선택도가 낮을 수록 인덱스 설정에 좋은 컬럼입니다.
5 ~ 10% 정도가 적당합니다.
데이터에서 특정 값을 얼마나 잘 선택할 수 있는지에 대한 지표입니다.
선택도는 아래와 같이 계산합니다.
컬럼의 특정 값의 row 수
/테이블의 총 row 수
*100
컬럼의 값들의 평균 row 수
/테이블의 총 row 수
*100
예를 들어, 10개 rows를 가지는 '학생' 테이블에 '학번', '이름', '성별' 컬럼이 있다고 해봅시다.
학번은 고유하고 이름은 2명씩 같고 성별은 남여 5:5 비율입니다.
- '학번'의 선택도 =
1
/10
*100
=10%
SELECT COUNT(1) FROM '학생' WHERE '학번' = 1;
모두 고유하므로 특정 값: 1
- '이름'의 선택도 =
2
/10
*100
=20%
SELECT COUNT(1) FROM '학생' WHERE '이름' = '김철수';
2명씩 같으므로 특정 값: 2
- '성별'의 선택도 =
5
/10
*100
=50%
SELECT COUNT(1) FROM '학생' WHERE '성별' = F;
5명씩 같으므로 특정 값: 5
즉, 선택도는 특정 필드값을 지정했을 때 선택되는 레코드 수를 테이블 전체 레코드 수로 나눈 것입니다.
✅ 활용도가 높을수록 인덱스 설정에 좋은 컬럼입니다.
해당 컬럼이 실제 작업에서 얼마나 활용되는지에 대한 값입니다.
수동 쿼리 조회, 로직과 서비스에서 쿼리를 날릴 때 WHERE절
에 자주 활용되는지를 판단하면 됩니다.
✅ 중복도가 없을 수록 인덱스 설정에 좋은 컬럼입니다.