MySQL이 인덱스를 사용하는 방식
MySQL이 인덱스를 사용하는 방식
인덱스는 특정 컬럼 값을 가진 행을 빠르게 찾기 위해 쓰는 구조예요. 인덱스가 없다면 MySQL은 첫 행부터 시작해서 전체 테이블을 통째로 읽어야 해요. 테이블이 커질수록 그 비용이 커지죠. 반대로 해당 컬럼에 인덱스가 있다면, MySQL은 처음 몇 개의 행만 확인하면 원하는 위치를 찾을 수 있어요. 인덱스가 어떤 원리로 동작하는지, 언제 효과적인지를 중심으로 설명할게요.
출처: https://dev.mysql.com/doc/refman/8.4/en/mysql-indexes.html
인덱스가 저장되는 구조
MySQL의 대부분 인덱스(PRIMARY KEY, UNIQUE, INDEX, FULLTEXT)는 B-트리(B-tree) 로 저장돼요. 단, 예외가 몇 가지 있는데요.
- 공간 데이터 타입의 인덱스는 R-트리(R-tree) 를 사용해요.
MEMORY테이블은 해시 인덱스(hash index)도 지원해요.InnoDB는FULLTEXT인덱스에 역목록(inverted list)을 사용해요.
MySQL이 인덱스를 사용하는 경우
MySQL은 크게 다음 같은 연산에서 인덱스를 활용해요.
- 검색(WHERE) — WHERE 절에 나온 컬럼 값과 일치하는 행을 빠르게 찾을 때.
- 조인(JOIN) — 두 테이블을 연결할 때 관련 컬럼의 인덱스를 사용해 결합 비용을 줄여요.
- 정렬(ORDER BY) — 인덱스는 정렬된 순서로 저장되므로, 별도 정렬 없이 키 순서대로 읽으면 정렬이 완료돼요.
- 집계(GROUP BY) — 비슷한 원리로 그룹별 집계를 빠르게 처리할 수 있어요.
- 커버링 인덱스(covering index) — 어떤 경우에는 데이터 행을 보지 않고 인덱스만으로 값을 가져오도록 쿼리를 최적화할 수 있어요. 인덱스가 필요한 모든 컬럼을 담고 있을 때 가능하죠.
인덱스가 덜 중요한 경우
인덱스가 항상 정답은 아니에요. 다음과 같은 상황에서는 인덱스의 이점이 작아져요.
- 테이블이 아주 작을 때 — 전체 테이블을 읽어도 부담이 없으니 인덱스가 크게 효율적이지 않아요.
- 쿼리가 대부분의 행을 읽을 때 — 보고용(report) 쿼리가 전체 또는 대부분의 행을 필요로 하면, 인덱스를 따라가며 읽는 것보다 순차(sequential) 읽기가 더 빨라요. 순차 읽기는 디스크 탐색(seek)을 최소화하거든요.
즉 "인덱스 = 무조건 빠름"이 아니라, 작은 테이블이나 대부분의 행을 읽는 쿼리에서는 오히려 전체 스캔이 유리할 수 있다는 점을 이해하는 게 핵심이에요.
더 알아보기
- 기본 키 최적화:
Section 10.3.2, "Primary Key Optimization" - B-트리와 해시 인덱스 비교:
Section 10.3.9, "Comparison of B-Tree and Hash Indexes" - ORDER BY·GROUP BY 최적화:
Section 10.2.1.16, "ORDER BY Optimization",Section 10.2.1.17, "GROUP BY Optimization" - 전체 테이블 스캔 피하기:
Section 10.2.1.23, "Avoiding Full Table Scans"