코딩관계론

MongoDB 쿼리 성능 이슈 및 인덱스 최적화 과정 본문

개발/Hot-Stock

MongoDB 쿼리 성능 이슈 및 인덱스 최적화 과정

개발자_티모 2025. 2. 10. 12:37
반응형

대규모 데이터 배치 작업 후, 검색 쿼리 성능이 현저히 저하되는 문제가 발생했습니다. 특히 특정 쿼리 수행 시간이 약 4초에 달했습니다.

 

성능 이슈 쿼리

1. 쿼리 실행 계획 분석

성능 저하 원인을 분석하기 위해 MongoDB의 쿼리 실행 계획을 확인했습니다.

db.news.find({'stockCode': '437730', 'isRelated': true}).explain("executionStats")

결과:

  • stage: COLLSCAN → 전체 컬렉션을 풀 스캔했습니다.
  • totalDocsExamined: 102,457 → 약 10만 건의 문서를 모두 검사했습니다.
  • nReturned: 8 → 최종 반환된 문서 수는 8건입니다.
  • executionTimeMillis: 3,374ms → 쿼리 한 번에 3초 이상 소요됐습니다.

결국, 인덱스가 없어 전체 데이터를 모두 스캔해 성능 저하가 발생한 것으로 확인됐습니다.

2. 인덱스 설계를 통한 성능 개선

MongoDB는 B-Tree 기반 인덱스를 사용하며, 주요 인덱스 유형은 다음과 같습니다.

  • 단일 인덱스: 한 필드에 대한 인덱스 (예: { stockCode: 1 })
  • 복합 인덱스: 여러 필드를 조합한 인덱스 (예: { stockCode: 1, isRelated: 1, isThema: 1 })
  • 멀티키 인덱스: 배열 필드에 자동 생성되는 인덱스

2.1 복합 인덱스의 선두 필드 중요성

복합 인덱스에서 선두 필드 배치는 성능에 큰 영향을 미칩니다.

  • 예시 (효율적): (stockCode, isRelated, isThema)
{
  "executionTimeMillis": 0,
  "totalKeysExamined": 8,
  "totalDocsExamined": 8,
  "stage": "FETCH",
  "inputStage": {
    "stage": "IXSCAN",
    "keyPattern": {"stockCode": 1, "isRelated": 1, "isThema": 1}
  }
}
  • 예시 (비효율적): (isRelated, stockCode, isThema)
{
  "executionSuccess": true,
  "nReturned": 8,
  "executionTimeMillis": 3374,
  "totalKeysExamined": 0,
  "totalDocsExamined": 102457,
  "executionStages": {
    "stage": "COLLSCAN",
    "filter": {"stockCode": "437730"}
  }
}

이유:

MongoDB는 B-Tree 인덱스 구조상 선두 필드를 기준으로 검색합니다. 선두 필드를 포함하지 않은 쿼리는 인덱스 효율성이 떨어져 결국 풀 스캔을 하게 됩니다.

3. Partial Index와 Sparse Index 활용

MongoDB는 특정 조건의 문서만 인덱싱하는 기능을 제공합니다.

  • Partial Index: 특정 조건을 만족하는 문서만 인덱싱
  • Sparse Index: 필드가 없는 문서는 제외

Partial Index 예시:

db.news.createIndex(
    { stockCode: 1, isRelated: 1, isThema: 1 },
    { partialFilterExpression: { isRelated: true } }
);

이를 통해 불필요한 인덱스 크기와 업데이트 부담을 줄일 수 있지만, 해당 조건 외의 쿼리는 여전히 풀 스캔이 발생할 수 있어 주의가 필요합니다.

4. 최종 성능 개선 결과

복합 인덱스와 Partial Index를 활용하여 쿼리 성능을 최적화한 결과, 실행 시간이 수 초에서 1ms 미만으로 극적으로 개선됐습니다.

{
  "executionSuccess": true,
  "nReturned": 8,
  "executionTimeMillis": 0,
  "totalKeysExamined": 8,
  "totalDocsExamined": 8,
  "stage": "FETCH",
  "inputStage": {
    "stage": "IXSCAN",
    "indexName": "stockCode_1_isRelated_1_isThema_1",
    "isPartial": true
  }
}

🎯 결론 및 핵심 포인트

  • 데이터 배치 후 성능 저하는 인덱스 부재나 설계 오류가 원인일 가능성이 높습니다.
  • MongoDB 복합 인덱스는 선두 필드(leading field)의 배치가 성능을 좌우합니다.
  • explain("executionStats")로 쿼리 실행 방식을 정확히 분석할 수 있습니다.
  • 필요에 따라 Partial Index와 Sparse Index를 적절히 활용해 인덱스 크기와 쓰기 부담을 관리해야 합니다.

최종적으로 쿼리 성능을 3초에서 1ms로 약 99%의 성능 향상 효과를 달성했습니다.

반응형