B-Tree(Balanced Tree) 구조를 기반으로 하며, 균형 잡힌 다진 트리로 구성. 모든 리프 노드가 동일한 깊이를 가지므로 검색, 삽입, 삭제 시 성능이 균일
범위 검색에 최적화되어 있어 특정 범위 내의 데이터를 빠르게 조회할 수 있음
인덱스 키가 정렬되어 저장되므로 정렬된 순서로 데이터를 효율적으로 검색
대부분의 관계형 데이터베이스 시스템(MySQL, PostgreSQL, Oracle, SQL Server 등)에서 기본 인덱스로 사용
단일 열 인덱스 및 복합 열 인덱스(여러 열을 결합한 인덱스)로 생성 가능
일반적인 검색, 정렬, 조인 연산에 적합
높은 검색 성능을 지녔으며 범위 검색에 유리하고 데이터 삽입, 삭제, 업데이트가 비교적 효율적이다.
but
대량의 데이터 삽입 시 인덱스 유지 관리 오버헤드 발생. 공간을 많이 차지할 수 있음.
해시 함수를 사용하여 키를 해시 테이블의 특정 버킷에 매핑
정확히 일치하는 값의 검색에 매우 빠름
해시 함수의 특성상 데이터가 정렬되지 않음
주로 메모리 기반 데이터베이스나 NoSQL 데이터베이스에서 사용
MySQL의 Memory 스토리지 엔진이나 PostgreSQL의 일부 확장 기능에서 사용
동등 검색에 대해 매우 빠른 성능 제공. 단순한 구조로 인한 낮은 검색 오버헤드
but
범위 검색 불가능. 해시 충돌이 발생할 경우 성능 저하. 데이터 정렬이나 순서 기반 검색에 부적합
각 키 값에 대해 비트맵(Bit Map)을 사용하여 해당 키 값이 있는 레코드를 표시
낮은 카디널리티(고유 값의 수가 적은 경우)에 특히 효율적
데이터 웨어하우스나 OLAP(Oline Analytical Processing) 환경에서 주로 사용
성별, 상태, 등과 같이 고유 값의 수가 적은 열에 적합
복잡한 논리 연산(AND, OR, NOT 등)을 빠르게 수행. 비트맵을 사용하여 공간을 절약
but
높은 카디널리티(고유 값의 수가 많은 경우)에서는 비효율적. 데이터 변경(삽입, 삭제, 업데이트) 시 비트맵 재구성이 필요하여 유지 관리가 복잡
테이블의 데이터 자체가 인덱스의 순서에 따라 물리적으로 정렬됨
하나의 테이블의 하나의 클러스터드 인덱스만 존재할 수 있음.
주로 기본 키(primary key)에 설정되며, 자주 검색되는 범위 쿼리에 유리
데이터와 인덱스가 동일한 구조이므로 데이터 접근이 빠름. 범위 검색, 정렬된 순서의 데이터 조회에 최적화
but
데이터 삽입, 삭제, 업데이트 시 물리적 재배치가 필요하여 성능 저하
클러스터드 인덱스가 있는 경우, 비클러스터드 인덱스가 클러스터드 인덱스의 키를 참조해야 하므로 추가적인 저장 공간이 필요.
데이터와 별도로 인덱스 구조가 존재하며, 인덱스는 데이터의 위치를 가리키는 포인터를 포함.
하나의 테이블에 여러 개의 넌클러스터드 인덱스를 생성할 수 있음
다양한 검색 조건에 대응하기 위해 사용
자주 사용되는 비클러스터드 인덱스를 생성하여 검색 성능 향상
여러 개의 넌클러스터드 인덱스를 통해 다양한 쿼리에 대응 가능. 데이터의 물리적 정렬에 영향을 주지 않음
but
인덱스가 많아질수록 쓰기 작업(삽입, 업데이트, 삭제) 시 오버헤드 증가. 추가적인 저장 공간이 필요.
텍스트 데이터를 효율적으로 검색하기 위해 설계된 인덱스.
단어 기반의 검색, 자연어 검색, 부분 일치 검색 등을 지원
대량의 텍스트 데이터(예: 문서, 기사, 블로그 등)에서 키워드 검색을 빠르게 수행
MySQL의 FULLTEXT 인덱스, PostgreSQL의 Full Text Search, SQL Server의 Full-Text Index 등이 있음.
복잡한 텍스트 검색 기능 제공. 대량의 텍스트 데이터에서 효율적인 검색 가능
but
인덱스 생성 및 유지 관리에 높은 비용이 소요. 정확한 일치 검색에는 적합하비 않음.
인덱스가 설정된 열의 값이 중복되지 않도록 강제
클러스터드 또는 넌클러스터드 인덱스로 생성 가능
데이터의 무결성을 유지하기 위해 사용.
기본 키나 고유 제약이 필요한 열에 주로 설정
중복 데이터를 방지하고 데이터 무결성 보장
but
인덱스 유지에 따른 추가적인 오버헤드, 중복된 값을 삽입하려 할 경우 오류 발생
두 개 이상의 열을 결합하여 생성된 인덱스
인덱스의 열 순서가 쿼리 성능에 영향을 미침
여러 열을 동시에 검색하거나 정렬하는 쿼리에 최적화
다중 조건 검색 시 인덱스 활용도를 높임
복합 조건 검색에서 높은 성능. 여러 열을 하나의 인덱스로 관리하여 저장 공간 절약 가능.
but
인덱스 생성 및 유지 관리 비용 증가. 열 순서에 따라 인덱스의 효율성이 달라짐.
테이블의 일부분에 대해서만 인덱스를 생성
특정 조건을 만족하는 행에 대해서만 인덱스를 생성
테이블의 전체 데이터가 아닌 특정 조건에 맞는 데이터에 대한 검색을 최적화
예를 들어, 활성 상태인 레코드에만 인덱스를 생성하여 검색 성능 향상
인덱스 크기 감소로 저장 공간 절약. 인덱스 유지 관리 오버헤드 감소. 특정 조건의 쿼리 성능 향상.
but
조건에 맞지 않는 쿼리에는 인덱스 활용 불가. 인덱스 설계가 복잡해질 수 있음.
Java Spring 백엔드 개발자 입장에서 위 인덱스 종류를 실습하며 학습할 수 있는 방법을 제안하겠습니다. 아래 단계는 데이터베이스 설계와 쿼리 작성, 그리고 성능 최적화를 직접 경험할 수 있도록 구성되어 있습니다.
Spring Data JPA, Spring Web, MySQL Driver 의존성 추가.실습 내용:
id, name, created_date를 가진 간단한 테이블 생성.실습 코드:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
created_date DATE,
INDEX idx_created_date (created_date)
);
-- 범위 검색 쿼리
EXPLAIN SELECT * FROM users WHERE created_date BETWEEN '2023-01-01' AND '2023-12-31';
Spring 실습:
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
List<User> findByCreatedDateBetween(LocalDate startDate, LocalDate endDate);
}
결과 확인:
EXPLAIN 결과에서 idx_created_date 인덱스가 사용되는지 확인.실습 내용:
Memory 엔진에서 해시 인덱스를 생성하고, 동등 검색 쿼리의 성능을 확인.실습 코드:
CREATE TABLE users_memory (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(50),
INDEX idx_email (email) USING HASH
) ENGINE=MEMORY;
-- 동등 검색 쿼리
EXPLAIN SELECT * FROM users_memory WHERE email = 'test@example.com';
Spring 실습:
결과 확인:
실습 내용:
name, created_date)을 결합한 복합 인덱스를 생성.실습 코드:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
created_date DATE,
INDEX idx_name_date (name, created_date)
);
-- 쿼리 1: name이 조건에 포함됨 -> 인덱스 사용
EXPLAIN SELECT * FROM users WHERE name = 'John' AND created_date > '2023-01-01';
-- 쿼리 2: created_date만 조건에 포함됨 -> 인덱스 미사용
EXPLAIN SELECT * FROM users WHERE created_date > '2023-01-01';
Spring 실습:
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
List<User> findByNameAndCreatedDateAfter(String name, LocalDate createdDate);
List<User> findByCreatedDateAfter(LocalDate createdDate);
}
결과 확인:
idx_name_date 인덱스가 언제 활용되는지 분석.실습 내용:
실습 코드:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY, -- Clustered Index
name VARCHAR(50),
created_date DATE,
INDEX idx_name (name) -- Non-Clustered Index
);
-- 클러스터드 인덱스 활용
EXPLAIN SELECT * FROM users WHERE id = 1;
-- 넌클러스터드 인덱스 활용
EXPLAIN SELECT * FROM users WHERE name = 'John';
결과 확인:
실습 내용:
MATCH()와 AGAINST()를 사용한 텍스트 검색 성능 확인.실습 코드:
CREATE TABLE posts (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255),
content TEXT,
FULLTEXT INDEX idx_fulltext_content (content)
);
-- Full-Text 검색
EXPLAIN SELECT * FROM posts WHERE MATCH(content) AGAINST('Spring Framework');
Spring 실습:
@Query(value = "SELECT * FROM posts WHERE MATCH(content) AGAINST(?1)", nativeQuery = true)
List<Post> searchByContent(String keyword);
실습 내용:
실습 코드:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
is_active BOOLEAN,
INDEX idx_active_users (id) WHERE is_active = TRUE
);
-- Partial Index 활용 쿼리
EXPLAIN SELECT * FROM users WHERE is_active = TRUE;
결과 확인:
EXPLAIN으로 확인.이러한 실습을 통해 인덱스 설계, 활용, 성능 분석에 대한 실질적인 이해를 얻을 수 있습니다. 또한, Spring Boot와 데이터베이스의 연계 작업에서 인덱스를 활용한 효율적인 쿼리 작성 능력을 기를 수 있습니다.
추가로 특정 실습 부분에서 더 깊이 다루길 원하면 알려주세요! 😊