문제의 쿼리

홈넷기기 조회 API의 경우 아래와 같은 쿼리를 발생한다.

{"$and": [{"siteId": "?"}, {"dong": "?"}, {"ho": "?"}]}
{"$and": [{"siteId": "?"}, {"dong": "?"}, {"ho": "?"}, {"homenetDeviceType": {"$in": ["?"]}}]}

해당 쿼리에 대한 쿼리 실행계획을 살펴보면 다음과 같은데

[
  {
    "$clusterTime": {
      "clusterTime": {"$timestamp": {"t": 1718106165, "i": 206}},
        마스킹
      }
    },
    "command": {
      "find": "마스킹",
      "filter": {
        "$and": [
          {"siteId": "마스킹"},
          {"dong": "마스킹"},
          {"ho": "마스킹"}
        ]
      },
      "$db": "마스킹"
    },
    "explainVersion": "1",
    "ok": 1,
    "operationTime": {"$timestamp": {"t": 1718106165, "i": 206}},
    "queryPlanner": {
      "namespace": "마스킹",
      "indexFilterSet": false,
      "parsedQuery": {
        "$and": [
          {"dong": {"$eq": "마스킹"}},
          {"ho": {"$eq": "마스킹"}},
          {"siteId": {"$eq": "마스킹"}}
        ]
      },
      "queryHash": "13E45E70",
      "planCacheKey": "B1D0A314",
      "maxIndexedOrSolutionsReached": false,
      "maxIndexedAndSolutionsReached": false,
      "maxScansToExplodeReached": false,
      "winningPlan": {
        "stage": "COLLSCAN",
        "filter": {
          "$and": [
            {"dong": {"$eq": "마스킹"}},
            {"ho": {"$eq": "마스킹"}},
            {"siteId": {"$eq": "마스킹"}}
          ]
        },
        "direction": "forward"
      },
      "rejectedPlans": []
    },
    "serverInfo": {
        마스킹
    },
    "serverParameters": {
        마스킹
    }
  }
]

winningPlan.stage 를 보면 COLLSCAN 으로 나와있는데 이는 collection scan을 의미하고 모든 도큐먼트를 스캔하여 쿼리 결과에 맞는 데이터를 조회하는 것을 의미한다.

인덱스

siteId, dong, ho이 공통적으로 사용되며 이를 복합 인덱스를 걸어보자

db.collection.createIndex({ siteId: 1, dong: 1, ho: 1 })

개선결과

실제로 3초 이상 걸리는 쿼리를 1초 미만으로 줄였다. (자료는 날라갔네요…)

추가로 알아보면 좋을 cursor.explain() 함수는 3가지 모드

queryPlanner 모드

  • MongoDB는 query optimizer를 실행하여 수행할 작업에 대한 winning plan를 선택하고, cursor.explain() 에 대한 평가된 query planner를 반환한다.
  • 쿼리를 실제로 수행하지 않는다.
  • rejected plan는 반환하지 않는다.

executionStats 모드

  • winning plan를 선택하고, query planner를 수행한 결과에 대한 지표를 반환한다.
  • winning plan에 대한 쿼리를 직접 수행하고 결과를 반환한다.
  • rejected plan는 반환하지 않는다.

allPlansExecution 모드

  • executionStats모드와 같이 winning plan를 선택하고 query palnner를 수행하여 이에 대한 통계 및 plan selection 중 캡처된 다른 winning plan에 대한 정보도 제공한다.
  • winning plan에 대한 쿼리를 직접 수행하고 결과를 반환한다.
  • rejected plan에 대한 정보도 제공한다.

Reference