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