✅ 인덱싱이란?
인덱스(Index)는 도서관의 목차와 비슷
책 전체를 읽지 않고도 원하는 정보를 빠르게 찾을 수 있도록 도와주는 구조.
📦 비유로 설명하면:
- 인덱스 없는 DB: “책 한 권 통째로 처음부터 끝까지 넘겨가며 찾는 것”
- 인덱스 있는 DB: “뒤쪽 목차나 페이지 번호 보고 바로 찾아가는 것”
✅ 인덱싱이 왜 중요한가?
- DB는 기본적으로 테이블의 모든 행을 탐색하는 풀 스캔(full scan) 방식.
- 데이터가 수천/수만 건 이상 쌓이면 검색이 선형 시간에 가까워져 성능이 급격히 저하.
- WHERE, JOIN, ORDER BY, GROUP BY, LIKE 조건에서 자주 사용되는 컬럼에 인덱스를 추가하면, 탐색 속도를 로그 시간 수준으로 줄일 수 있음.
✅ 인덱스가 필요한 상황 (예시)
SELECT * FROM book
WHERE title LIKE '%한강%'
OR author LIKE '%한강%';
- book 테이블에 데이터가 10건이면 상관없지만,
- 5만 건 이상이면 "title" + "author" 조건 탐색은 비효율적인 full scan이 될 수 있음.
✅ 인덱스 적용 DDL (복합 인덱스 예시)
-- title, author 컬럼에 복합 인덱스 생성
CREATE INDEX idx_book_title_author
ON book (title, author);
- title + author는 검색 조건에서 자주 사용되니, 인덱스를 적용하는 게 타당함.
- 단일 컬럼 인덱스가 아니라 복합 인덱스로 설정한 이유는 조합 조건 최적화 때문.
✅ 인덱스 전후 쿼리 속도 비교 예시 (실제 실행 계획으로 비교 가능)
항목 | 인덱스 적용 전 | 인덱스 적용 후 |
Rows Examined | 50,000 | 123 |
실행 시간 | 2.8초 | 0.03초 |
explain type | ALL (Full Table Scan) | range (Index Scan) |
possible_keys | NULL | idx_book_title_author |
실제 쿼리 속도는 EXPLAIN 명령어로 확인할 수 있음:
EXPLAIN SELECT * FROM book WHERE title LIKE '%한강%';
✅ 쿼리 성능을 위해 더 고려할 점
항목 |
내용 |
와일드카드 위치 | %한강%처럼 앞에 %가 붙으면 인덱스 무효화 → 한강% 또는 fulltext로 대체 |
조건 컬럼 수 | 여러 조건(title + author + publisher)이 있을 땐 복합 인덱스 |
자주 쓰이는 쿼리 | SELECT COUNT(*) FROM …, WHERE 조건 등도 인덱스로 최적화 가능 |
중복 제거 | OpenAPI 데이터 적재 시 중복 데이터도 인덱스로 빠르게 검사 가능 |
✅ 정리
구분 | 설명 |
인덱스란? | 테이블의 데이터를 빠르게 찾기 위한 자료 구조 (B+ Tree 등) |
언제 필요? | 데이터가 많고, 특정 컬럼 조건으로 자주 조회할 때 |
예시 | 검색 키워드(title, author) 조건 자주 쓰일 때 |
주의할 점 | 과도한 인덱스는 insert 성능 저하, LIKE ’%abc%’는 인덱스 무효화 |
🛠️ 검색 기능에서 인덱스 최적화 적용 요약
- 개선 대상 쿼리:
SELECT * FROM book WHERE title LIKE '%한강%' OR author LIKE '%한강%';
- 이유: 검색 조건이 자주 쓰이며, 대량 데이터에서 느려질 수 있음
- DDL:
CREATE INDEX idx_book_title_author ON book (title, author);
- 성능 개선 기대: Full Scan → Index Scan 으로 변환되어 수천 배 빠르게 탐색 가능
✅ 1. 인덱스(Index)는 언제 적용되나?
인덱스는 “WHERE”, “JOIN”, “ORDER BY”절에 사용되는 컬럼에 대해
DB가 빠르게 검색할 수 있도록 도와주는 자료구조입니다.
예를 들어 다음과 같은 쿼리:
SELECT * FROM book WHERE title = '...' AND author = '...' AND publisher = '...';
이 쿼리에서 title, author, publisher 컬럼에 인덱스가 잡혀 있으면,
→ 전체 테이블을 Full Scan 하지 않고
→ B-Tree 구조의 인덱스를 따라 바로 해당 Row 위치로 Jump 할 수 있습니다.
✅ 2. 현재 코드에서 인덱스가 적용되는 위치는?
바로 여기입니다:
queryFactory
.selectFrom(book)
.where(
book.title.in(titles),
book.author.in(authors),
book.publisher.in(publishers)
)
.fetch();
이 때 실제 실행되는 쿼리는 대략 다음과 같습니다:
SELECT * FROM book
WHERE title IN (...)
AND author IN (...)
AND publisher IN (...);
→ 이 조건이 title, author, publisher 컬럼의 인덱스를 타게 됩니다.
그리고 실제로 당신이 선언한 이 인덱스:
@Table(name = "book", indexes = {
@Index(name = "idx_book_title_author", columnList = "title, author"),
@Index(name = "idx_book_title_author_publisher", columnList = "title, author, publisher", unique = true)
})
→ title + author + publisher 조합을 커버하므로
→ WHERE title IN ... AND author IN ... AND publisher IN ... 쿼리에 정확하게 적용됩니다.
✅ 3. 인덱스가 실제로 적용되었는지 확인하는 방법
MySQL에서 아래와 같은 명령어를 실행해 보세요:
EXPLAIN SELECT * FROM book
WHERE title IN ('A', 'B')
AND author IN ('홍길동')
AND publisher IN ('민음사');
결과에 key: idx_book_title_author_publisher가 나오면
→ 해당 인덱스가 적용되었음을 의미합니다.
✅ 4. 정리 – 지금 구조는 올바른가?
항목 | 상태 | 설명 |
인덱스 선언 | ✅ O | title + author + publisher로 유니크 인덱스 설정 |
다건 exists 조회 개선 | ✅ O | List<Book> findExistingBooks(...) 로 일괄 조회 |
조건 컬럼과 인덱스 일치 여부 | ✅ O | WHERE title IN (...) AND author IN (...) AND publisher IN (...) 사용 |
성능 개선 가능성 | ✅ 높음 | 인덱스 + 일괄 조회 + Set 중복 제거 로 구조 최적화됨 |
✅ 인덱스는 WHERE 절에서 해당 컬럼들이 사용될 경우 DB가 자동으로 인덱스를 사용합니다.
당신이 다음과 같이 인덱스를 선언했잖아요:
@Table(name = "book", indexes = {
@Index(name = "idx_book_title_author", columnList = "title, author"),
@Index(name = "idx_book_title_author_publisher", columnList = "title, author, publisher", unique = true)
})
이건 실제 DDL로 보면 MySQL에서는 대충 이렇게 나옵니다:
CREATE UNIQUE INDEX idx_book_title_author_publisher
ON book (title, author, publisher);
🔍 그러면 이런 WHERE 절을 썼을 때:
SELECT * FROM book
WHERE title = '채식주의자'
AND author = '한강'
AND publisher = '창비';
→ 이 조건이 정확히 title, author, publisher 순서로 일치하니까,
→ RDBMS는 해당 인덱스를 “자동”으로 사용합니다.
⚠️ 다만 순서와 완전성이 중요합니다
예를 들어:
WHERE 절 조건 | 인덱스 사용 가능 여부 | 이유 |
title AND author AND publisher | ✅ 가능 | 인덱스 정의 순서와 정확히 일치 |
title AND author | ✅ 가능 | 정의된 인덱스의 앞쪽만 사용해도 됨 |
author AND publisher | ❌ 불가 | 인덱스 정의된 순서의 앞부분(title)이 빠짐 |
publisher만 | ❌ 불가 | 마찬가지로 첫 번째 컬럼 누락 |
✅ 정리
인덱스는 WHERE 절의 조건이 인덱스의 정의된 순서와 맞아야 제대로 동작합니다.
- @Index(columnList = "title, author, publisher") 선언했으면→ 또는 WHERE title = ? AND author = ? 까지는 OK
- → WHERE author = ? AND publisher = ? 는 NO (title 빠짐)
- → WHERE title = ? AND author = ? AND publisher = ?
🔧 확인 팁
MySQL 쓴다면 아래처럼 실행 계획으로 실제 사용됐는지 확인하세요:
EXPLAIN SELECT * FROM book
WHERE title = '채식주의자'
AND author = '한강'
AND publisher = '창비';
→ 결과에서 key: idx_book_title_author_publisher가 나오면
→ 진짜 인덱스를 타고 있는 겁니다.
'코딩 > sparta TIL' 카테고리의 다른 글
한 프로젝트에서 서버를 분리하는 방법과 프로젝트별 서버 분리 후 연동하는 방법 (백엔드) (0) | 2025.05.29 |
---|---|
실전 프로젝트 - 트러블 슈팅 (1) | 2025.05.26 |
CI/CD (0) | 2025.05.25 |
Docker를 이용한 로컬 배포 진행해보기 (0) | 2025.05.25 |
Native Query(네이티브 쿼리) (0) | 2025.05.22 |