MongoDB 서버도 세컨드리 인덱스를 지원하므로 하나의 컬렉션은 최소 1개 이상의 인덱스를 가질 수 있다.
여러 개의 인덱스를 가지고 있을 때는 각 쿼리를 실행할 때 어떤 인덱스를 사용하는 것이 최적인지 확인하고 사용할 인덱스를 선별하는 작업이 필요하다.
MongoDB 에서 같은 패턴의 쿼리는 같은 실행 계획을 재활용할 수 있도록 실행계획을 캐시하는 기능이 있다.
실행 계획
쿼리의 처리 과정
MongoDB 서버는 쿼리를 처리하기 위해 실행 계획을 사용하는데, 이 실행 계획은 트리 구조의 스테이지로 구성된다.
실행계획 예시를 들어본다.
실행계획 | 설명 |
FETCH -> IXSCAN | 인덱스 레인지 스캔을 실행한 다음 컬렉션 데이터 파일에서 도큐먼트를 읽음 |
SORT -> COLLSCAN | 컬렉션 풀 스캔으로 조건에 일치하는 도큐먼트를 읽은 다음 정렬을 수행 |
SORT -> FETCH -> IXSCAN | 인덱스 레인지 스캔을 실행한 다음 컬렉션 데이터 파일에서 도큐먼트를 읽고 그 결과를 정렬 |
FETCH -> SORT_MERGE -> IXSCAN | 인덱스 인터섹션으로 레인지 스캔을 실행한 다음 컬렉션 데이터 파일에서 도큐먼트를 읽음 |
실행 계획의 트리는 최상위의 스테이지를 루트 스테이지라고 하며, 쿼리 실행이 시작되면 루트스테이지는 자신의 자식 스테이지를 호출한다. 이 때 각 스테이지를 호출하는 API 의 이름이 work 인데 실행계획에서는 이를 works 라는 단어로 표현한다.
각 스테이지의 work 함수 호출은 대표적으로 다음 3종류의 리턴 값을 반환한다.
리턴 값 | 설명 |
ADVANCE | 스테이지 처리 결과 한 건의 도큐먼트 또는 ID 값을 반환 |
NEED_TIME | 스테이지 처리는 완료했지만 결과 도큐먼트나 ID 값은 반환되지 않음 주로 블록킹 스테이지일 때 발생하는데, 대표적인 블록킹 스테이지로는 인덱스를 사용하지 못하는 정렬이나 그룹핑 스테이지가 있음 |
IS_EOF | 스테이지 처리는 완료됐으며 더이상 읽을 도큐먼트나 ID 값이 없음 |
상위 스테이지에서 하위 스테이지의 work 함수를 호출하는 것은 하나의 단위 작업인데, work 함수의 호출은 주로 도큐먼트 단위로 호출이 이뤄진다.
실행계획을 보여주는 결과는 explain("executionStats") 를 실행할 때만 표시되며, 실행 계획상 표시되는 모든 스테이지에 대해 내용들이 출력된다.
실행 계획 결과에서 works 와 advanced 그리고 needTime 값은 실행 계획상 각 스테이지의 어떤 단계에서 얼마나 도큐먼트를 읽고 버렸는지 얼마나 정렬을 수행했는지 등을 확인할 수 있는 중요한 정보이다.
실행 계획 수립
MongoDB 서버는 한번 실행됐던 쿼리의 실행 계획은 캐시에 저장해두고 같은 패턴의 쿼리가 다시 요청되면 캐시된 실행 계획을 활용한다.
요청된 쿼리가 캐시에 저장된 실행계획과 같은 패턴인지 비교하기 위해 아래 3가지 정보를 사용한다.
- 쿼리 조건
- 정렬 조건
- 조회 필드
이 3가지 내용을 묶어 MongoDB 에서는 "Query Shape" 라고 하는데 검색과 정렬 조건에 사용된 필드가 같고 조회하는 필드가 같으면 같은 "Query Shape" 로 판단한다.
LIMIT 이나 SKIP 조건은 포함되지 않으므로 모두 같은 패턴의 쿼리로 판단하고 같은 실행 계획을 사용하게 된다.
쿼리의 실행 계획이 저장된 캐시가 사용되는 방법이다.
1. 쿼리가 요청되면 옵티마이저는 플랜 캐시에서 같은 패턴의 쿼리가 이미 캐시되어있는지 확인한다.
2. 일치하는 쿼리 패턴의 실행 계획이 없으면 새롭게 쿼리의 실행 계획을 수립한다.
3. MongoDB 서버는 성능과 관계없이 가능한 모든 실행 계획을 준비하고 실제로 각 후보 실행 계획들을 이용해서 쿼리를 실행한다.
4. 제일 먼저 쿼리가 실행 완료되거나 지정된 도큐먼트 건수를 가장 먼저 반환하는 실행 계획을 선택한다.
- 이렇게 선택된 실행 계획을 Winning Plan 이라 하고 버려진 실행 계획을 Rejected Plan 이라 한다.
5. 선택된 실행 계획은 이후 같은 패턴의 쿼리 실행을 위해 플랜 캐시에 저장되고 활용한다.
만약 실행하고자 하는 쿼리와 일치하는 쿼리 패턴의 실행 계획이 있으면 MongoDB 서버는 캐시된 실행 계획의 성능을 재확인하는 과정을 거친다. 이 과정을 통과하면 서버는 그 실행 계획을 이용해 쿼리 실행 단계로 바로 넘어간다.
하지만 실패하게 되면 캐시된 실행 계획이 없을 때와 동일하게 가능한 실행 계획을 준비하고 최종 실행 계획을 선택해서 쿼리를 실행하는 과정을 거친다.
컬렉션이 삭제되거나 해당 컬렉션의 인덱스가 추가 생성 또는 삭제되는 경우 해당 컬렉션의 캐시된 실행 계획은 모두 삭제되고 이후 실행되는 쿼리에 대해 실행 계획이 다시 수립되어 캐시되는 과정을 거친다.
옵티마이저 옵션
MongoDB 서버는 각 컬렉션에 대한 통계 정보가 거의 없다. 그나마 유일한 통계 정보가 컬렉션의 전체 도큐먼트 건수 정도인데, 이 수치는 실제 쿼리 실행을 위해 효율적인 인덱스를 선택하는 데 큰 도움이 되지 않는다.
그래서 쿼리의 검색과 정렬조건 그리고 조회하고자 하는 필드를 이용해 거의 기계적으로 사용 가능한 실행 계획을 생성한다. 여기저 기계적이라는 표현은 규칙 기반의 옵티마이저를 의미한다.
하지만 규칙 기반의 실행 계획은 허점이 많아 MongoDB 서버는 준비된 실행 계획 후보들을 모두 동시에 실행해보는 형태로 규칙 기반의 실행 계획의 단점을 보완한다.
최적의 실행 계획을 찾는 과정에서 다음과 같은 내부 설정값을 사용한다.
설정 명 | 기본 값 | 설명 |
internalQueryPlanEvaluationCollFraction | 0.3 | |
internalQueryPlanEvaluationMaxResults | 101 | 옵티마이저가 최적의 실행 계획을 선택할 때 얼마나 많은 도큐먼트가 반환될 때까지 실행할 것인지 결정하는 옵션 여러개의 실행 계획 중 101건을 먼저 반환하는 실행 계획을 최적의 실행 계획으로 선택 |
internalQueryPlanEvaluationWorks | 10000 | |
internalQueryPlanOrChildrenIndependently | true | |
internalQueryPlannerEnableHashIntersection | false | 인덱스 인터섹션 최적화를 사용할 것인지 결정 인덱스 인터섹션은 활성화되어 있지만 해시 인터섹션은 비활성 상태 여러 인덱스를 핸들링해서 결과를 병합해야 하므로 성능이 좋지 않음 |
internalQueryPlannerEnableIndexIntersection | true | |
internalQueryPlannerMaxIndexedSolutions | 64 |
MongoDB 서버의 실행 계획은 works 상태 값과 advance 상태 값의 비율을 이용해서 최적의 실행 계획을 수립한다.
MongoDB 서버는 internalQueryPlanEvaluationCollFraction 과 internalQueryPlanEvaluationWorks 옵션을 이용해 실행 계획 수립 과정에서 사용할 수 있는 최대 works 의 횟수를 결정한다.
그리고 지정된 work 함수 호출 횟수 내에 internalQueryPlanEvaluationMaxResults 옵션에 명시된 건수만큼 도큐먼트를 먼저 반환하는 실행 계획을 최적 실행 계획으로 판단한다.
플랜 캐시
최적의 쿼리 실행 계획을 수립하기 위해 사용할 수 있는 실행 계획을 모두 직접 실행해보고 그중 최적의 계획을 선택한다.
그래서 쿼리가 느리다면 실제 실행계획을 수립하는 과정도 많은 시간이 걸리기도 하며, 이러한 이유로 선택된 실행 계획은 플랜 캐시에 저장하고 이후 쿼리들이 재사용할 수 있게 한다.
다만 아래 조건의 이벤트가 발생하면 플랜 캐시에서 해당 컬렉션과 관련된 실행 계획이 모두 제거되고 다시 최적의 실행 계획을 찾는 과정이 반복된다.
- 컬렉션의 인덱스가 생성되거나 삭제되는 경우
- 컬렉션의 reIndex() 명령이 실행되는 경우
- MongoDB 서버가 재시작되는 경우
MongoDB 3.0 버전부터 컬렉션의 쓰기 횟수에 관계없이 플랜 캐시의 실행 계획은 그대로 유지하도록 개선되었다.
하지만 많은 쓰기 오퍼레이션 이후에 데이터 분포도가 변경될 때를 대비해서 쿼리가 실행될 때마다 플랜 캐시의 실행 계획에 대해서 간단히 평가하는 단계를 구현했다. 이렇게 매번 쿼리가 플랜 캐시의 실행 계획을 평가하고 성능이 나쁜 경우에는 해당 실행 계획을 처음부터 다시 수집해서 최적의 계획을 선택하는 과정을 수행한다.
쿼리가 실행될 때마다 플랜 캐시에서 가져온 실행 계획은 재평과 가정을 거치는데, 이때 재평가 과정은 통과(Pass) 또는 실패(Not Pass)로 결정된다.
실행 계획의 재평가는 지정된 만큼의 도큐먼크만 읽어서 internalQueryPlanEvaluationMaxREsults 옵션에 정의한 수만큼 도큐먼트를 가져올 수 있는지 판단하는 형태로 지정되는데, 이 때 최대 읽을 수 있는 "지정된 만큼의 도큐먼트" 는 아래 수식으로 결정된다.
( 최초 실행 계획을 수립할 때 work() 함수의 호출 횟수) * internalQueryCacheEvictionRatio
만약 지정된 도큐먼트 건수만큼 읽었는데 internalQueryCacheEvictionRatio 에 설정된 건수만큼의 도큐먼트를 가져오지 못하면 현재 실행 계획을 버리고 새롭게 실행 계획 후보를 뽑아서 그중 최적의 실행 계획을 선택하는 과정을 밟게 된다.
플랜 캐시는 최대 5천개의 실행 계획을 저장할 수 있도록 초기 설정돼 있으며
실행 계획을 캐시해야 하는 쿼리 패턴이 5천개가 넘는 경우 사용되지 않는 쿼리의 실행 계획이 플랜 캐시에서 삭제되고 새로운 실행 계획이 캐시에 저장된다.
만약 패턴이 5천개를 넘는다면 internalQueryCacheSize 값을 변경해 플랜캐시에 저장할 수 있는 실행 계획의 수를 늘릴 수 있다.
MongoDB 에서는 관리자가 플랜 캐시의 내용을 확인할 수 있도록 PlanCache 객체와 관련된 기능을 제공한다.
PlanCache 객체는 컬렉션 단위로 캐시된 실행 계획을 확인할 수 있다.
그런데 한번이라도 실행됐다고 해서 모든 쿼리의 실행 계획이 PlanCache 에 저장되는 것은 아니며 실행계획이 단 하나밖에 없는 경우에는 PlanCache 에 저장되지 않는다.
캐시에 저장된 실행 계획 중에서 특정 쿼리 패턴으로 상세한 실행 계획을 확인할 수 있다.
플랜 캐시에서 특정 실행 계획을 삭제하고자 한다면 다음과 같이 clear() 명령이나 clearPlansByQuery() 명령을 이용하면 된다. clearPlansByQuery() 명령은 쿼리의 패턴으로 특정 실행 계획만 삭제하지만 clear 명령은 현재 컬렉션의 모든 실행 계획을 삭제하므로 많은 쿼리를 처리하고 있는 MongoDB 서버에서는 사용을 주의해야 한다.
실행 계획 스테이지
실행 계획을 이용해서 쿼리의 성능을 가늠하려면 각 스테이지가 어떤 역할을 수행하는지에 대해 알아야 한다.
역할 | 설명 |
COLLSCAN | 컬렉션 풀 스캔 스테이지 |
IXSCAN | 컬렉션의 인덱스를 이용해서 인덱스 레인지 스캔 접근 방식으로 데이터를 읽는 스테이지 |
QUEUED_DATA | 입력 데이터 없이 데이터를 생성해내는 스테이지 중 하나로 컬렉션 없이 자체적으로 임시 데이터를 만듬 |
FETCH | 인덱스 레인지 스캔으로 읽은 인덱스 키와 RecordId 를 이용해 컬렉션의 도큐먼트를 읽는 스테이지 |
AND_SORTED | 인덱스 인터섹션 실행 계획을 사용할 때, 각 인덱스를 통해 읽은 도큐먼트의 교집합을 찾는 스테이지 |
COUNT | 자식 스테이지에 반환된 도큐먼트의 건수를 누적하는 스테이지 |
COUNT_SCAN | count() 명령이 인덱스를 사용할 수 있을 때 사용되는 스테이지 |
DISTINCT_SCAN | 인덱스 키를 순차적으로 읽으면서 유니크한 값이 나타날 때만 부모 스테이지로 결과를 반환하는 스테이지 |
GROUP | db.collection.group 명령이나 Aggregation 의 $group 파이프라인을 위해 사용되는 스테이지로 그룹핑 필드별로 전체 결과를 모아서 한번에 부모 스테이지로 념겨주는 역할 |
IDHACK | _id 필드를 동등 비교로 검색하는 쿼리는 빠른 경로로 쿼리를 처리하는 최적화를 수행하여 IDHACK 스테이지라 함 |
INDEX_ITERATOR | 인덱스 스캔을 이용하는 커서를 이용해 끝까지 인덱스 키를 읽는 스테이지 |
LIMIT | 쿼리에서 limit 이 사용된 경우 지정된 N 건의 도큐먼트만 반환하는 스테이지 |
SKIP | 쿼리에서 skip 이 사용된 경우 지정된 M 건의 도큐먼트를 버리고 나머지를 반환하는 스테이지 |
SORT_MERGE | 두 개 이상의 자식 노드에서 반환된 결과 집합을 병합하는 스테이지 |
SORT | 인덱스를 이용하지 못하는 정렬 처리를 위해 MongoDB 서버가 쿼리 실행 시점에 도큐먼트의 정렬을 수행하는 스테이지 |
TEXT | 쿼리의 전문 검색 조건은 항상 TEXT 스테이지로 시작해 TEXT_MATCH 그리고 TEXT_OR 스테이지로 구성됨 |
UPDATE | 도큐먼트의 데이터를 변경하는 작업을 처리하는 스테이지 |
DELETE | 도큐먼트의 데이터를 삭제하는 작업을 처리하는 스테이지 |
대부분은 FETCH, UPDATE, DELETE, IXSCAN 으로 될 것 같고 SORT, GROUP, LIMIT, SKIP 이 뜸뜸하게 보일 것 같다.
쿼리 실행 계획 해석
실행 계획은 cursor.explain() 으로 확인할 수 있는데 크게 3가지 모드를 지원한다.
모드 | 설명 |
queryPlanner | cursor.explain() 명령은 아무런 옵션이 없으면 디폴트 모드인 queryPlanner 로 작동한다. queryPlanner 모드에서는 해당 쿼리를 위해 선택된 최적의 실행 계획만 보여주는데, 3가지 모드 중 가장 단순한 실행 계획 결과를 보여준다. 이 결과로 아래 튜닝 정보를 분석할 수 있다. - 쿼리가 의도했던 인덱스를 제대로 활용하는지 - 쿼리가 정렬 작업을 인덱스를 활용하는지 - 쿼리의 프로젝션이 인덱스를 이용해 처리되는지 수행하면 queryPlanner 필드가 최상위에 나타나고 winingPlan 필드가 표시되는데 이 하위의 내용이 최적으로 선택된 실행 계획의 내용을 보여준다. winningPlan 하위에 트리 형태의 스테이지 구성이 표시되는데 현재 쿼리를 실행하기 위해 사용되는 각 단계를 보여준다. |
executionStats | executionStats 모드에서는 queryPlanner 모드의 모든 내용을 포함하고 더불어 선택된 최적실행계획을 실행하고 실행된 내역을 상세히 보여주는 실행 계획 모드 이 결과로 아래 튜닝 정보를 분석할 수 있다. - 인덱스의 선택도가 좋은지 - 실행 계획의 각 처리 단계에서 어떤 스테이지가 느린지 수행하면 executionStats 모드의 실행 계획이 추가로 표시되고 work 함수가 몇 번 호출되었는지 응답으로 ADVANCE 나 NEED_TIME 등이 몇 번 반환됐는지 등의 상세한 정보를 보여준다. |
allPlansExecution | 옵티마이저가 최적으로 선택한 실행 계획과 그 실행 계획의 상세 내역을 포함하며, 더불어 옵티마이저가 최적의 실행 계획을 선택하기 위해 평가했던 나머지 후보 실행 계획들의 내용도 모두 포함 이 결과로 아래 튜닝 정보를 분석할 수 있다. - 옵티마이저가 여러 실행 계획들을 검토했는지 - 여러 실행 계획 중 왜 최적 실행 계획이 선택되었는지 allPlansExecution 필드가 추가로 표시되며 이 필드 하위에는 후보실행 계획별로 하나씩 배열로 표시된다. |
queryPlanner 모드의 출력
winningPlan 필드에는 스테이지가 트리 형태로 표시되는데, 이는 최적의 실행 계획이 사용하는 스테이지별로 정보를 보여준다.
실행계획을 보면 SORT -> SORT_KEY_GENERATOR -> FETCH -> IXSCAN 스테이지가 트리 형태로 구성되어 있다.
SORT 스테이지는 SORT_KEY_GENERATOR 스테이지를 포함하고 있으므로 SORT 스테이지가 부모 스테이지이다.
MongoDB 서버가 쿼리를 실행할 때 호출 순서는 부모에서 자식 스테이지로 흘러가지만, 실제로 처리되는 순서는 반대로 자식 스테이지가 제일 먼저 실행되고 그 다음에 부모 스테이지가 실행되는 순서이다.
그래서 이 경우 IXSCAN 이 가장 먼저 실행되고 그 결과르 검색된 도큐먼트의 ID 가 반환된다.
FETCH 스테이지에서 도큐먼트 ID 를 이용해서 실제 컬렉션 데이터 파일에서 도큐먼트를 가져오는 작업을 수행한다.
읽어온 도큐먼트에 대해 SORT_KEY_GENERATOR 스테이지가 정렬 조건을 이용해 정렬 키를 생성한다.
마지막으로 최상위 SORT 스테이지는 정렬 키를 이용해 정렬을 수행하고 클라이언트로 반환한다.
인덱스와 관련된 indexBounds 필드에는 인덱스 레인지 스캔을 위한 범위를 보여주는데 이 범위는 실제 인덱스를 읽는 범위를 확인할 수 있다.
executionStats 모드의 출력
executionStats 는 우선 n4Returned, executionTimeMillis, totalKeysExamined, totalDocsExamined 은 똑같이 표시되는데 전체적인 실행결과 상태 정보를 보여주는 것이므로 하위의 각 스테이지에 표시되는 상태 값들의 합계로 생각하면 된다.
상태 | 설명 |
n4Returned | 실제 클라이언트로 반환된 도큐먼트의 건수 |
executionTimeMillis | 전체 쿼리의 실행 시간 (밀리초) |
totalKeysExamined | 쿼리를 처리하기 위해 인덱스에서 읽은 인덱스 키의 개수 |
totalDocsExamined | 쿼리를 처리하기 위해 컬렉션의 데이터 파일에서 읽은 도큐먼트의 개수 |
executionStats 필드하위에 executionStages 필드가 표시되는데, 쿼리의 실행계획에 표시되었던 각 스테이지들이 실행되는 동안 처리한 상세한 내용이 표시된다.
executionStages 하위 스테이지들이 트리 구조로 표시된다.
상태 | 설명 |
stage | 현재 스테이지의 타입 |
executionTimeMillisEstimate | 현재 스테이지(자식 스테이지를 포함)를 처리하는데 걸린 밀리초 |
executionTimeMillisEstimated | 현재 스테이지를 처리하는데 걸린 밀리초 |
works | 현재 스테이지의 work 함수가 호출된 횟수 |
advanced | 현재 스테이지가 도큐먼트를 반환한 횟수 |
needTime | 현재 스테이지가 도큐먼트를 반환하지 못한 횟수 |
needYield | 현재 스테이지가 처리되면서 Yield 를 실행한 횟수 |
isEOF | 현재 스테이지가 EOF 를 반환한 횟수 |
9-4 쿼리를 실행하기 위해 4개의 스테이지를 거쳐서 실행됐는데, SORT_KEY_GENERATOR 와 FETCH , IXSCAN 스테이지는 5~6번만 호출되었고 이 스테이지들의 work 함수 리턴 값은 대부분 ADVANCED 이다.
즉 이 스테이지들은 대부분 work 함수가 호출될 때마다 도큐먼트 결과를 한 건씩 리턴했다는 것을 알 수 있다.
하지만 제일 앞쪽의 SORT 스테이지는 12번이 호출되었고 그 중 6번은 NEED_TIME 을 리턴하였다.
그러면서도 실제 리턴된 도큐먼트 건수는 4건밖에 안된다.
단순히 work 함수의 호출 횟수가 성능을 결정하는 것은 아니지만, 내부적으로 각 스테이지에서 어떤 작업을 얼마나 반복해서 많이 수행하는지 판단할 수 있다.
스테이지별로 작업의 특성에 따라 추가로 표시되는 내용도 있다.
SORT 경우 memUsage 와 memLimit 필드가 출력되는데 정렬을 처리하기 위해 사용할 수 있는 최대 메모리 버퍼 크기와 처리를 위해 사용한 정렬용 메모리 버퍼의 크기를 의미한다.
allPlansExecution 모드의 출력
allPlansExecution 필드는 옵티마이저가 검토했던 모든 예비 실행 계획 후보들을 실행한 후, 각 실행 계획별로 실행 상태 정보를 알려준다.
{ score:1 , name:1 } | { name:1 } | |
totalKeysExamined | 11 | 4 |
totalDocsExamined | 11 | 4 |
works | 11 | 11 |
advanced | 0 | 4 |
needTime | 11 | 6 |
isEOF | 0 | 1 |
쿼리를 처리하는데 있어 {name:1} 인덱스를 사용한 실행 계획은 인덱스 키 엔트리를 단지 4개만 읽고, 컬렉션의 데이터 파일에서도 4개의 도큐먼트만 읽어서 쿼리를 종료했다는 것을 알 수 있다. 반면 {score:1 , name:1} 은 11개씩 읽었다.
실제 루트 스테이지의 work 함수 호출 횟수는 두 실행 계획 모두 11이라는 값을 보여준다.
둘 다 11번의 work 함수가 호출되었는데 name:1 이 효율적이라 판단한 이유는 실행 계획 수립 과정에 있다.
MongoDB 옵티마이저는 최적의 실행계획을 선택하기 위해 가능한 모든 실행 계획 후보를 동시에 병렬로 실행한다.
그리고 돌아가면서 각 실행계획의 루트 스테이지에 대해 work 함수를 균등하게 한 번씩 호출한다.
이렇게 반복해서 실행 계획의 work 함수를 호출하면서 2개 조건 중 하나라도 충족되는 실행계획이 나올때까지 실행한다.
- 특정 실행 계획의 처리가 완료
- 특정 실행 계획이 101건(internalQueryPlanEvaluationMaxResults 의 값)의 도큐먼트를 반환
이 예제에서는 인덱스를 사용하는 실행 계획이 11번의 work 함수 호출 후 처리가 완료되어
더이상 다른 실행계획을 평가하지 않고 종료한다.
이렇게 후보 실행 계획 중 먼저 완료된 실행 계획이 있는 경우에는 isEOF 필드의 값이 1인 경우가 있는지 확인한다.
실제 쿼리가 무겁고 많은 도큐먼트를 처리해야 하는 쿼리일수록 실행 계획을 선정하는 작업이 시간이 오래 걸릴 수밖에 없는 이유이다. 또한 쿼리의 실행 계획을 처음 수립하는 과정에서 가능한 모든 후보 실행 계획을 동시에 실행해야 하므로 서버에 부담이 간다.
UPDATE 와 REMOVE 그리고 AGGREGATION 쿼리의 실행계획
UPDATE 나 REMOVE 명령에 대해서는 explain().update() 혹은 explain().delete() 형태로 실행 계획을 확인할 수 있는 문법을 지원한다.
'Database > MongoDB' 카테고리의 다른 글
[MongoDB] 보안(1) (1) | 2024.11.26 |
---|---|
[MongoDB] 실행 계획 및 쿼리 최적화(2) (0) | 2024.11.25 |
[MongoDB] 쿼리 개발과 튜닝(1) (6) | 2024.10.06 |
[MongoDB] 데이터 모델링 (1) | 2024.09.19 |
[MongoDB] 잠금과 트랜잭션(2) (0) | 2024.09.09 |