[DB] index 의 적용 기준

calis_ws·2024년 2월 16일
0

인덱스는 테이블의 동작 속도를 높여주는 자료 구조이다.
데이터의 위치를 빠르게 찾아주는 역할을 한다.

쉬운 예시로, 책 뒷 편에 ‘색인’이 바로 이 인덱스의 역할이라고 보면 된다.
색인을 통해 원하는 키워드에 대한 페이지로 바로 이동할 수 있다.

책의 색인이 여러 페이지에 기재되어 있는 것처럼
DB의 인덱스가 잘 설정되었을 경우, 데이터베이스 메모리에 일정 공간을 사용해 저장이 되고, 데이터를 조회할 때 소모되는 메모리를 효율적으로 사용하게 한다.

인덱스의 특징

인덱스는 WHERE 절에서 효과가 있다

인덱스는 SELECT - FROM - WHERE 절 중 WHERE 절에 사용할 컬럼에 대한 효율화라고 볼 수 있다.

WHERE 절을 사용하지 않고 인덱스가 걸린 컬럼을 조회하는 것은 성능에 아무런 영향이 없다.

예를 들어, ‘학생’ 테이블에 ‘학번’, ‘이름’, ‘전화번호’가 있다고 가정해보자.
인덱스는 ‘학번’, ‘전화번호’에 걸려 있다.

다음 중 인덱스가 영향을 주는 쿼리는 어떤 것일까?

1) SELECT '학번' FROM '학생';
2) SELECT '전화번호' FROM '학생' WHERE '이름' = "김철수";
3) SELECT * FROM '학생' WHERE '학번' = 1;

정답은 3번)
WHERE 절에 사용할 때 성능을 향상시킨다.

무조건 많이 설정하면 좋은걸까?

인덱스는 하나 혹은 여러 개의 컬럼에 대해 설정할 수 있다.
단일 인덱스를 여러 개 생성할 수도, 여러 컬럼을 묶어 복합 인덱스를 설정할 수도 있다.

그러나 무조건 많이 설정하는게 검색 속도 향상을 높여주지는 않는다.
인덱스는 데이터베이스 메모리를 사용하여 테이블 형태로 저장되므로 개수와 저장 공간은 비례한다.

따라서, 조회시 자주 사용하고 고유한 값 위주로 인덱스를 설정하는게 좋다.

DML(Data Manipulation Language) 각각에는 어떤 영향을 미칠까?

SELECT 쿼리에서 성능이 잘 나오지만, INSERT, UPDATE, DELETE 쿼리에서는 때에 따라 다르다.

UPDATE, DELETE 는 WHERE 절에 잘 설정된 인덱스로 조건을 붙여주면 조회할 때 성능은 크게 저하되지 않으나
(업데이트 할 데이터를 찾을 때의 속도가 빨라지는 것이지, 업데이트 자체가 빨라지는 것은 아님!)

INSERT 의 경우, 새로운 데이터가 추가되면서 → 기존에 인덱스 페이지에 저장되어 있던 탐색 위치가 수정되어야 하므로 효율이 좋지 않다.

즉, 인덱스는 원하는 데이터를 빠르게 찾을 때 빛을 발한다.

그럼 어떤 컬럼에 인덱스를 설정하는게 좋을까?

인덱스는 한 테이블당 보통 3~5개 정도가 적당하다.
물론 테이블의 목적 등에 따라 개수는 달라질 수 있다.

인덱스는 컬럼을 정해서 설정하는 것이므로 후보 컬럼의 특징을 잘 파악해야 한다.
아래 4가지 기준을 사용하면 효율적으로 인덱스를 설정할 수 있다.

카디널리티 (Cardinality)

✔️ 카디널리티가 높을 수록 인덱스 설정에 좋은 컬럼이다.
= 한 컬럼이 갖고 있는 값의 중복 정도가 낮을 수록 좋다.

컬럼에 사용되는 값의 다양성 정도, 즉 중복 수치를 나타내는 지표이다.
후보 컬럼에 따라 상대적으로 중복 정도가 낮다, 혹은 높다로 표현된다.

예를 들어, 10개 rows를 가지는 ‘학생’ 테이블에 ‘학번’과 ‘이름’ 컬럼이 있다고 해보자.

  • ‘학번’은 학생마다 부여 받으므로 10개 값 모두 고유하다.
    • 중복 정도가 낮으므로 카디널리티가 높다.
  • ‘이름’은 동명이인이 있을 수 있으니 1~10개 사이의 값을 가진다.
    • 중복 정도가 ‘학번’에 비해 높으므로 카디널리티가 낮다고 표현할 수 있다.

선택도 (Selectivity)

✔️ 선택도가 낮을 수록 인덱스 설정에 좋은 컬럼이다.
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 절에 자주 활용되는지를 판단하면 된다.

중복도

✔️ 중복도가 낮을 수록 인덱스 설정에 좋은 컬럼이다.

중복도는 인덱스로 선택된 값이 얼마나 고유한지를 나타낸다.

중복도가 낮을수록 인덱스의 효과가 높아진다.
즉, 인덱스로 선택된 값이 서로 다른 레코드에서 자주 발생하는 경우에는 인덱스가 더 유용합니다.

예를 들어, 성별 열은 중복도가 높지만 주민등록번호와 같은 고유한 값은 중복도가 매우 낮다.


정리

인덱스는 WHERE 절에서 사용할 때 성능을 향상시킨다.

조회 시 자주 사용하고 고유한 값 위주로 인덱스를 설정하는게 좋다.

  • 카디널리티 : 높을 수록 적합
  • 선택도 : 낮을 수록 적합 (5~10% 적정)
  • 활용도 : 높을 수록 적합
  • 중복도 : 낮을 수록 적합

이러한 요소들을 고려하여 인덱스를 설계하면 데이터베이스의 성능을 최적화할 수 있다.

출처

https://yurimkoo.github.io/db/2020/03/14/db-index.html

profile
반갑습니다람지

0개의 댓글