데이터베이스 테이블의 검색(SELECT) 속도를 획기적으로 향상시켜주는 자료구조
인덱스가 없을 때
책에서 특정 단어를 찾으려면 첫 페이지부터 끝까지 모든 페이지(Full Scan)를 확인
-> 데이터베이스에서는 테이블의 모든 행을 확인
-> 느림
인덱스가 있을 때
책의 목차나 색인을 통해 원하는 내용이 몇 페이지에 있는지 확인하고, 그 페이지로 바로 이동
-> 데이터베이스에서는 인덱스에서 데이터의 물리적 주소를 찾아 바로 접근
-> 빠름
특징
데이터를 정렬된 상태로 유지
리프 노드에만 실제 데이터를 저장하거나 데이터의 포인터를 저장하며, 이 리프 노드들은 링크드 리스트로 연결
사용 목적
범위 검색(<, >, BETWEEN) 및 정렬(ORDER BY)에 매우 효율적이며, 대부분의 관계형 데이터베이스(RDB) 인덱스의 기본값
특징
키 값에 해시 함수를 적용하여 해시 테이블 형태로 저장
데이터가 정렬되어 있지 않음
사용 목적
동등 비교 검색(=)시 주소를 O(1)로 가장 빠르게 검색
제한
데이터가 정렬되어 있지 않아 범위 검색이나 정렬에는 사용 불가(DBMS에 따라 지원 여부 및 활용 범위가 다름)
역할
인덱스의 리프 노드가 실제 데이터 행 자체
데이터의 물리적인 저장 순서가 이 인덱스 순서대로 정렬
개수
테이블당 오직 1개만 생성 가능, 주로 Primary Key(기본 키) 지정 시 자동으로 생성
조회
인덱스 검색 후 데이터에 바로 접근(1단계) -> 가장 빠른 조회 제공
역할
데이터와 별도로 생성
리프 노드에는 컬럼 값과 해당 데이터의 클러스터드 키 값(또는 물리적 주소)만 저장
개수
테이블당 여러 개 생성 가능
조회
세컨더리 인덱스 검색 -> 클러스터드 키 획득 -> 클러스터드 인덱스를 통해 테이블 접근(2단계)이 필요
WHERE, ORDER BY, JOIN 절에 자주 사용되는 컬럼| 컬럼 | 인덱스 유형 | |
|---|---|---|
| member_id | INT | Primary Key(클러스터드 인덱스 자동 생성) |
| memeber_name | VARCHAR | |
| VARCHAR | ||
| join_date | DATE |
-- (기본값) B+Tree 세컨더리 인덱스 생성
CREATE INDEX idx_members_join_date ON members (join_date);
-- 특정 자료구조 명시 (DBMS가 지원하는 경우)
CREATE INDEX idx_members_email ON members (email) USING HASH;
쿼리가 요구하는 모든 컬럼이 인덱스에 포함되도록 인덱스를 설계하여, 실제 테이블 접근(Table Fetch) 없이 인덱스만으로 조회를 완료
-- 복합 인덱스 생성 (이름 검색 후 가입일 조회에 사용)
CREATE INDEX idx_members_name_date ON members (member_name, join_date);
-- 쿼리: 이름으로 검색하고 가입일만 조회
-- 이 경우, 인덱스(member_name, join_date)만 읽어 결과를 반환 (최적의 성능)
EXPLAIN SELECT member_name, join_date FROM members
WHERE member_name = '홍길동';
인덱스를 만들더라도, 데이터베이스 내부의 옵티마이저(Optimizer)가 쿼리 실행 시 비용을 계산하여 인덱스 스캔보다 Full Scan이 빠르다고 판단하면 인덱스를 사용하지 않을 수 있음 (ex. 조회하려는 데이터 비율이 전체의 10~20%를 초과할 때)