Db인덱스
title: 2026-03-19 author: 김희원 date: 2026-03-19 category: TIL/김희원/2026/03 layout: post —
데이터베이스 인덱스
- 테이블의 검색 속도를 향상시키기 위한 자료구조
- 저장되는 칼럼 값으로 항상 정렬된 상태를 유지한다
- 조회는 빠르게 돕지만, insert, update, delete 성능은 저하된다.
인덱스를 구성하는 자료구조
- MySQL InnoDB 기준 B-Tree 자료구조를 이용함
- B-Tree 자료구조의 특징
- 최상위 루트 노드 하나, 가장 하위 노드는 리프 노드, 그 사이에 브랜치 노드
- 리프 노드 → 클러스터링 인덱스냐 세컨더리 인덱스냐에 따라서 달라진다
- B-Tree랑 B+Tree의 차이
클러스터링 인덱스
- 리프 노드에 실제 데이터 row를 저장한다
세컨더리 인덱스
- 리프 노드에 PK 값만 저장한다.
- PK 인덱스를 다시 조회하러 가야 함 → Double Lookup
커버링 인덱스
- 인덱스만으로 쿼리를 해결하는 경우로, 테이블 접근이 필요없음
SELECT name FROM user WHERE age = 20;- (age, name) 인덱스가 있으면 테이블 안 보고 인덱스만 읽는다
- 랜덤 I/O를 제거할 수 있어 매우 빠름
- 이유: 인덱스만으로 데이터를 조회 → 테이블 접근 X
EXPLAIN쿼리에서 Using Index만으로 해결되는 것을 볼 수 있다
복합 인덱스 & Leftmost Prefix Rule
- 복합 인덱스는 선행 컬럼부터 순서대로 사용해야 함
INDEX (A, B, C)→ A/ AB/ ABC 가능 ↔ B/ BC/ C 불가능
인덱스를 타지 않는 경우
- 함수를 사용/ LIKE %/ 타입 불일치/ OR 조건/ ORDER BY(경우에 따라)
- B-Tree 정렬 구조를 활용할 수 없어서 인덱스 또한 사용이 안됨
WHERE YEAR(created_at) = 2024(X) →WHERE created_at >= '2024-01-01'- ORDER BY → 인덱스 정렬 순서랑 다르면 추가 정렬 file sort가 필요함
인덱스 선택도
- 얼마나 데이터를 잘 걸러내는가의 개념
- 성별 (X) 주민번호 (O)
- 카디널리티가 높은 컬럼이 인덱스에 유리함
실무: 옵티마이저 & 실행 계획 EXPLAIN
- EXPLAIN 결과에서 읽어내면 좋은 거 → 인덱스가 사용되는지 검증해야 함
- type → ALL/RANGE/REF
- key → 사용된 인덱스
- rows → 예상 스캔 수
인덱스 설계 기준
- WHERE > JOIN > ORDER BY / GROUP BY
스캔 방식
1. 인덱스 레인지 스캔
- 인덱스에서 조건 범위에 해당하는 일부 구간만 읽는 방식
- 과정
- index seek: 인덱스에서 조건을 만족하는 값이 저장된 리프 노드 찾음
- index scan: 시작 리프 노드부터 필요한 만큼 인덱스를 순차 탐색
- 인덱스 키, PK 값 → 저장된 페이지 가져와서 읽음
-
예시
WHERE age = 10 WHERE age BETWEEN 10 AND 20 WHERE age > 10
2. 인덱스 풀 스캔
- 인덱스를 처음부터 끝까지 전부 읽는 방식
- 언제 쓰냐?
- 인덱스는 쓰는데 조건이 비효율적이라서 인덱스 전체를 읽는 게 더 나을 때
WHERE B = 10→ (A, B) 인덱스에서 A 없이 사용
- 데이터보다 인덱스가 작을 때
- 인덱스는 쓰는데 조건이 비효율적이라서 인덱스 전체를 읽는 게 더 나을 때
3. 루스 인덱스 스캔 Loose Index Scan
- 필요한 인덱스 값만 건너뛰면서 읽는다
-
GROUP BY/ MIN / MAX 최적화에서 사용되는 특수한 접근 방식
SELECT col1, MIN(col2) FROM table GROUP BY col1;
4. 풀 테이블 스캔 (ALL)
- 인덱스를 사용하지 않고 전체 테이블을 읽는 방식
- 순차 I/O
- 대량 데이터 조회 시 유리하다