쿼리 계획
이 페이지의 내용
MongoDB 쿼리 플래너는 주어진 쿼리에 대해 사용 가능한 인덱스를 고려하여 가장 효율적인 쿼리 계획을 선택하고 캐시합니다. 쿼리 계획의 효율성을 평가하기 위해 쿼리 플래너는 평가 기간 동안 모든 후보 계획을 실행합니다. 일반적으로 평가 기간 동안 가장 적은 양의 작업을 수행하면서 가장 많은 결과를 생성하는 쿼리 계획이 채택됩니다.
관련 계획 캐시 항목은 동일한 쿼리 형태를 가진 후속 쿼리에 사용됩니다.
다음 다이어그램에서는 쿼리 플래너 로직을 보여 줍니다.
참고
explain
을 사용하면 기존의 모든 계획 캐시 항목이 무시되고 MongoDB 쿼리 플래너가 새 계획 캐시 항목을 만들 수 없습니다.
계획 캐시 항목 상태
각 계획 캐시 쿼리 형태는 캐시의 세 가지 상태 중 하나와 연결됩니다.
상태 | 설명 |
---|---|
이 모양에 대한 항목이 캐시에 존재하지 않습니다. 쿼리 의 경우 쿼리 형태 에 대한 캐시 항목 상태 가 누락인 경우:
| |
계획 캐시 변경을 트리거하다 하는 추가 시나리오는 계획 캐시 플러시를 참조하세요.
쿼리 계획 및 캐시 정보
특정 쿼리에 대한 쿼리 계획 정보를 보려면 db.collection.explain()
또는 cursor.explain()
를 사용할 수 있습니다.
컬렉션에 대한 계획 캐시 정보를 보려면 $planCacheStats
집계 단계를 사용할 수 있습니다.
계획 캐시 플러시
mongod
가 다시 시작되거나 종료되면 쿼리 계획 캐시가 지속되지 않습니다. 또한:
인덱스 또는 컬렉션 제거와 같은 카탈로그 작업은 계획 캐시를 지웁니다.
최소 사용 (LRU) 캐시 교체 메커니즘은 상태에 관계없이 가장 최근에 액세스한 캐시 항목을 지웁니다.
사용자는 또한 다음을 수행할 수 있습니다.
PlanCache.clear()
방법을 사용하여 전체 계획 캐시를 수동으로 지웁니다PlanCache.clearPlansByQuery()
방법을 사용하여 특정 계획 캐시 항목을 수동으로 지웁니다
플랜 캐시 디버그 정보 크기 제한
MongoDB 5.0부터 계획 캐시는 모든 컬렉션에 대한 plan caches
의 누적 크기가 0.5 GB보다 작은 경우에만 전체 plan cache
항목을 저장합니다. 모든 컬렉션에 대한 plan caches
의 누적 크기가 이 임계값을 초과하면 다음 디버그 정보 없이 추가 plan cache
항목이 저장됩니다.
plan cache
항목의 예상 크기 (바이트) 는 $planCacheStats
출력에서 사용할 수 있습니다.
queryHash
개인정보 정책에 planCacheKey
queryHash
동일한 쿼리 형태를 가진 느린 쿼리를 식별하는 데 도움이 되도록 각 쿼리 형태는 queryHash와 연결됩니다. queryHash
는 쿼리 형태의 해시를 나타내며 쿼리 형태에만 종속되는 16진수 문자열입니다.
참고
다른 해시 함수와 마찬가지로, 두 개의 다른 쿼리 형태가 동일한 해시 값을 생성할 수 있습니다. 그러나 서로 다른 쿼리 형태 간에 해시 충돌이 발생할 가능성은 거의 없습니다.
planCacheKey
MongoDB는 쿼리 계획 캐시에 대한 더 많은 인사이트를 제공하기 위해 planCacheKey
를 제공합니다.
planCacheKey
은 쿼리와 연관된 플랜 캐쉬 (plan cache) 항목에 대한 키의 해시입니다.
참고
queryHash
와 달리 planCacheKey
쿼리 형태와 형태에 대해 현재 사용 가능한 색인 모두를 고려한 함수입니다. 즉, 쿼리 형태를 지원할 수 있는 인덱스를 추가 혹은 삭제되면 planCacheKey
값은 변경될 수 있지만 queryHash
값은 변경되지 않습니다.
예를 들어 다음 인덱스가 있는 컬렉션 foo
을 생각해 보겠습니다:
db.foo.createIndex( { x: 1 } ) db.foo.createIndex( { x: 1, y: 1 } ) db.foo.createIndex( { x: 1, z: 1 }, { partialFilterExpression: { x: { $gt: 10 } } } )
컬렉션에 대한 다음 쿼리는 형태가 동일합니다.
db.foo.explain().find( { x: { $gt: 5 } } ) // Query Operation 1 db.foo.explain().find( { x: { $gt: 20 } } ) // Query Operation 2
이러한 쿼리가 주어지면 부분 필터 표현식이 있는 인덱스는 쿼리 작업 2를 지원할 수 있지만 쿼리 작업 1은 지원할 수 없습니다 . 쿼리 작업 1을 지원하는 데 사용할 수 있는 인덱스가 쿼리 작업 2와 다르기 때문에 두 쿼리의 planCacheKey
는 서로 다릅니다.
인덱스 중 하나가 제거되거나 새 인덱스 { x: 1, a: 1
}
가 추가된 경우 두 쿼리 작업의 planCacheKey
값이 변경됩니다.
가용성
queryHash
과 planCacheKey
은 다음과 같은 곳에서 사용할 수 있습니다.
explain() 출력 필드:
queryPlanner.queryHash
및queryPlanner.planCacheKey
프로파일러 로그 메시지와 진단 로그 메시지(예: mongod/mongos 로그 메시지)를 저속 쿼리를 로깅할 때 사용합니다.
$planCacheStats
집계 단계PlanCache.listQueryShapes()
method/planCacheListQueryShapes
명령PlanCache.getPlansByQuery()
method/planCacheListPlans
명령
인덱스 필터
인덱스 필터는 planCacheSetFilter
명령으로 설정되,며 플래너가 쿼리 형태에 대해 평가하는 인덱스를 결정합니다. 쿼리 형태는 쿼리, 정렬 및 프로젝션 사양의 조합으로 구성됩니다. 지정된 쿼리 형태에 대한 인덱스 필터가 있는 경우 플래너는 필터에 지정된 인덱스만 고려합니다.
쿼리 형태에 대한 인덱스 필터가 있는 경우, MongoDB는 hint()
를 무시합니다. MongoDB가 쿼리 형태에 인덱스 필터를 적용했는지 확인하려면 indexFilterSet
db.collection.explain()
cursor.explain()
또는 메서드의 필드를 확인합니다.
인덱스 필터는 쿼리 플래너가 평가하는 인덱스에만 영향을 미칩니다. 즉, 플래너는 특정 쿼리 형태에 대해 여전히 컬렉션 스캔을 최적의 계획으로 선택할 수 있습니다.
이러한 인덱스 필터는 서버 프로세스가 실행되는 동안에만 유효하며, 서버가 종료되면 사라집니다 MongoDB는 사용자가 수동으로 이러한 필터를 제거할 수 있는 명령을 제공합니다.
인덱스 필터는 플래너의 기대 동작과 hint()
메서드의 작동을 변경하기 때문에, 인덱스 필터 사용은 신중하게 결정해야 합니다.
MongoDB 6.0부터 인덱스 필터는 이전에 명령을 planCacheSetFilter
사용하여 설정한 데이터 정렬을 사용합니다.