코딩/sparta TIL

최적화(인덱싱 Indexing)

americanoallday 2025. 5. 25. 16:54

✅ 인덱싱이란?

인덱스(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가 나오면

→ 진짜 인덱스를 타고 있는 겁니다.