대규모 데이터 환경에서 쿼리 성능을 최적화하는 핵심 기술 중 하나는 Covered Index(Index-only Query) 를 활용하는 것이다. Covered Index는 쿼리 처리에 필요한 모든 정보가 인덱스 안에 포함되어 있어 Document 본문을 읽을 필요가 없는 경우를 의미한다.
즉, Disk I/O 없이 인덱스만으로 결과를 반환할 수 있어 속도와 리소스 효율성이 매우 뛰어나다.

 

1. Covered Index란 무엇인가?

MongoDB에서 쿼리가 Covered Index가 되기 위한 조건은 다음과 같다:

  • 필터 조건이 인덱스 필드에 포함되어야 한다. find()의 where 조건 필드가 인덱스에 존재해야함 
  • Projection 필드와 인덱스 필드가 일치해야 한다. 반환해야 하는 필드가 전부 인덱스에 포함되어야 한다. 
  • _id를 제외해야 하는 경우가 많다. _id는 자동 포함되므로 필요 없으면 _id:0 명시
  • 정렬을 사용하는 경우 정렬 필드도 인덱스 사용, sort 대상 또한 인덱스 안에 있어야 fetch 발생이 없다. 

Fetch 발생하는 경우

IXSCAN → FETCH → PROJECTION

중간에 FETCH가 있으면 문서를 읽은 것 → Covered Index가 아님.

 

진짜 Covered 라면

IXSCAN → PROJECTION_COVERED 

여기에서 explain 결과가 "totalDocsExamined": 0 나온다. 

 

2. 인덱스 생성 예시

db.movies.createIndex(
  { type: 1, genres: 1, year: -1, title: 1 },
  {
    name: "type_genres_year_title_movieOnly",
    partialFilterExpression: { type: "movie" }
  }
);

 Partial Index를 사용하는 경우

  • 인덱스 크기 감소 - 전체 문서 중에 type : movie 만 포함시킨다. 
  • 선택도 향상 - 불필요한 값이 포함되지 않는다. 
  • 스캔 범위 축소 가능 - 쿼리 최적화 가능 

MongoDB Cluster 에서 Index 생성

3. Covered Index를 활용하는 쿼리 예시

Non Covered Index 적용 시 

db.movies.find(
  { type: "movie", genres: "Drama" }
).sort({ year: -1 });

Covered Index 에서 적용되지 않은 사례

db.movies.find(
  { type: "movie", genres: "Drama" },
  { title: 1, year: 1, _id: 0 }
).sort({ year: -1 });

Covered Index 적용된 사례

결과 Explain Plan

totalDocsExamined 0

IXSCAN -> PROJECTION_COVERED
totalDocsExamined: 0

Document Fetch 없이 인덱스만으로 결과 처리 가능 

Sort도 인덱스로 해결 -> in-memory sort가 없다. 

 

4. Projection이 왜 중요한가?

아래 예시는 Covered Index가 깨지는 경우:

db.movies.find(
  { type: "movie", genres: "Drama" },
  { title: 1, year: 1, rated: 1, _id: 0 }
)
  • rated 필드가 인덱스에 없다. 이러면 결국 본문에서 읽어야 한다. 
  • 결과적으로 fetch 발생하게 된다. -> covered 불가 

5. Covered Index 활용 가능한 케이스들

  • Projection Covered -> find, project, sort 를 같이한다.
  • index-only distinct -> db.movies.distinct("genres") 인덱스 포함시
  • count 최적화 -> count()가 인덱스로만 가능 
  • index intersection (제한) -> 여러 인덱스 조합 

6. Covered 여부 확인 checklist

  • explain("executionStats") 결과 확인 가능 
"totalDocsExamined": 0
"totalKeysExamined": N
"stage": "PROJECTION_COVERED"

Explain Tree 예시

PROJECTION_COVERED (4ms)
 └── IXSCAN (7ms)

7. 정리

기능 비-covered covered(Index-only)
I/O 비용 높음 낮음
응답성능 느림 대부분 빠름
필드 요구사항 제한 없음 필드가 모두 인덱스에 존재해야함 

Covered Index는 MongoDB 성능 최적화의 핵심 기술이며,
특히 대용량 조회 API, 검색 리스트 화면, 정렬 포함 목록 페이징, 통계 조회 등에서 큰 효과를 볼 수 있겠다.