저번 포스팅에서는 캐싱과 레디스를 사용하여 DB 가 가지는 부하를 줄이는 방법에대해 고민하였다. 이번 포스팅에는 인덱스를 적용하기전 인덱스가 무엇이고 어떤 부분을 고려해야할지 간단히 알아보겠다.
검색하면 다 나오는 세상이지만 잠깐 정리하고자 인덱스가 무엇인지 아주 살짝만 가져와보았다.
덱스(영어: index)는 데이터베이스 분야에 있어서 테이블에 대한 동작의 속도를 높여주는 자료 구조를 일컫는다. 인덱스는 테이블 내의 1개의 컬럼, 혹은 여러 개의 컬럼을 이용하여 생성될 수 있다. 고속의 검색 동작뿐만 아니라 레코드 접근과 관련 효율적인 순서 매김 동작에 대한 기초를 제공한다. 인덱스를 저장하는 데 필요한 디스크 공간은 보통 테이블을 저장하는 데 필요한 디스크 공간보다 작다. (왜냐하면 보통 인덱스는 키-필드만 갖고 있고, 테이블의 다른 세부 항목들은 갖고 있지 않기 때문이다.) 관계형 데이터베이스에서는 인덱스는 테이블 부분에 대한 하나의 사본이다. 위키백과-인덱스
💡 다량의 트래픽이 유입될 때, 데이터의 조회 쿼리 성능은 "인덱스"와 함께 하느냐, 아니냐에 따라 하늘과 땅 차이다!
인덱스는 조회 성능을 높일 수 있지만 아래 사항들을 고려하여 설계해야 함
- 한번에 찾을 수 있는 값 - 데이터 중복이 적은 컬럼
- 인덱스 재정렬 최소화 - 데이터 삽입, 수정이 적은 컬럼
- 인덱스의 목적은 검색 - 조회에 자주 사용되는 컬럼
- 너무 많지 않은 인덱스 - 인덱스 또한 공간을 차지함
인덱스 대상 컬럼의 핵심은 높은 카디널리티(Cardinality) (데이터의 중복 수치)
(1) 나이 → 연령대가 많이 차이나지 않으므로 많은 데이터를 걸러낼 수 없음.
(2) 성별 → 50% 의 데이터만 걸러낼 수 있으므로 성별 기준 전체 조회가 아니면 유의미하지 않음.
(3) 이름, 계좌번호 → 중복값이 거의 없으므로 검색 조건과 일치하지 않는 데이터 대부분을 걸러낼 수 있음.
여러 컬럼으로 이루어진 인덱스에서는 일반적으로 카디널리티가 높은 순 으로 배치
CREATE INDEX IDX_P_STATUS ON ORDER_ITEM (product_id, order_status)
반드시 첫번째 인덱스 조건 은 조회 조건 중 하나에 포함되어야 함
복합 Index 의 경우 조건 순서와 일치시킬수록 높은 성능을 가짐
인덱스 컬럼의 값과 타입을 그대로 사용할 것 ( 인덱스는 컬럼의 값만 알고 있음 )
## price 컬럼에 Index 가 적용된 경우
# 올바른 인덱스 사용
where price > 10000 / 100; // price 컬럼에 대한 Index Search
## 잘못된 인덱스 사용
where price * 100 > 10000; // price * 100 에 대한 Index X
LIKE, BETWEEN, <, > 등 범위 조건의 컬럼은 Index 가 적용되나 그 뒤 컬럼은 Index 적용 x
범위 조건의 경우, Index 사용에 유의할 것
## Index(product_id, ordered_at, count, is_abroad) is_abroad : 해외 배송 여부
where product_id = 1 and is_abroad = 1 and ordered_at > '2024-01-01'
## product_id = Index
## ordered_at = Index
## is_abroad = Index X
1 2024-01-01 5 true
2 2024-01-02 3 true
3 2024-01-03 2 false
4 2024-01-04 1 false
# NOTE: datetime, id 처럼 카디널리티가 높은(데이터중복도가 낮은) 필드 이후에는
# 복합인덱스를 추가해도 의미 없는 인덱스가 될 확률이 매우 높음
AND 는 ROW 를 줄이지만 OR 는 비교를 위해 ROW 를 늘리므로 Full-Scan 발생확률이 높음
WHERE 절에서
OR
연산을 사용할 때는 이를 고려하자
=, IN 은 다음 컬럼도 인덱스를 사용한다.
IN 은 = 연산을 여러번 수행한 것이므로 다음 컬럼도 인덱스를 태울 수 있음.
💡 Covering Index