이 장에서는 몽고디비 쿼리 성능 분석을 소개합니다. SQL의 explain과 유사하게, 몽고디비도 쿼리 문의 성능을 분석하는 explain을 지원합니다.

기본 사용법

explain 함수를 호출하여 분석 결과를 얻을 수 있습니다.

// find 메서드의 분석 결과
db.collection.find({}).explain();

// aggregate 메서드의 분석 결과
db.collection.explain().aggregate([]);

explain에는 세 가지 모드가 있습니다:

  • queryPlanner (기본값)
  • executionStats
  • allPlansExecution

설명:

  • queryPlanner를 사용하면 모든 가능한 실행 계획을 나열하고 실제 문을 실행하지 않으며 이미 이긴 winningPlan 계획을 표시합니다.
  • executionStats를 사용하면 이긴 winningPlan 계획만 실행하고 결과를 출력합니다.
  • allPlansExecution을 사용하면 모든 계획을 실행하고 결과를 출력합니다.

다른 모드의 사용법

// executionStats 모드, 단순히 explain 함수에 매개변수를 전달
db.collection.find({}).explain('executionStats');

// allPlansExecution 모드
db.collection.find({}).explain('allPlansExecution');

explain 내용 설명

queryPlanner 내용

explain으로 반환되는 기본 내용은 다음과 같습니다.

{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "test.orders",
		"indexFilterSet" : false, // 키 메트릭, 인덱스 필터링 데이터를 사용하는지 여부
		"winningPlan" : {
			"stage" : "COLLSCAN", // 키 메트릭, 단계 이름. 각 단계에는 단계별 정보가 있으며 COLLSCAN은 전체 컬렉션 콘텐츠를 스캔하는 것을 나타냅니다
			"direction" : "forward"
		},
		"rejectedPlans" : [ ]
	}
	...
}

단계 유형은 다음과 같습니다:

  • COLLSCAN: 전체 테이블 스캔
  • IXSCAN: 인덱스 스캔
  • FETCH: 인덱스를 기반으로 특정 문서를 검색
  • SHARD_MERGE: 각 샤드가 반환한 데이터 병합
  • SORT: 메모리에서 정렬을 나타냄
  • LIMIT: 반환되는 수를 제한
  • SKIP: 사용하지 않고 건너뛰기
  • IDHACK: _id에 대한 쿼리
  • SHARDING_FILTER: 몽고스를 통해 조각화된 데이터 조회
  • COUNT: db.coll.explain().count() 또는 유사한 카운트 작업에 사용되는 단계 반환
  • COUNTSCAN: 카운트에 인덱스를 사용하지 않고 카운트하는 경우의 단계 반환
  • COUNT_SCAN: 카운트에 인덱스를 사용하여 카운트하는 경우의 단계 반환
  • SUBPLA: $or 쿼리에 인덱스를 사용하지 않고 단계 반환
  • TEXT: 전체 텍스트 인덱스를 사용하여 조회하는 경우의 단계 반환
  • PROJECTION: 반환되는 필드를 제한하는 단계 반환

executionStats 내용

executionStats 모드에서 반환되는 내용은 다음과 같습니다.

{
	"executionStats" : {
		"executionSuccess" : true,
		"nReturned" : 5, // 반환된 문서 수
		"executionTimeMillis" : 0, // 실행 시간
		"totalKeysExamined" : 0, // 스캔된 인덱스 수
		"totalDocsExamined" : 5, // 스캔된 문서의 총 수
		"executionStages" : {
			"stage" : "COLLS CAN", // 단계 유형, COLLSCAN은 전체 테이블을 스캔하는 것을 의미합니다
			"nReturned" : 5,
			"executionTimeMillisEstimate" : 0,
			"works" : 7,
			"advanced" : 5,
			"needTime" : 1,
			"needYield" : 0,
			"saveState" : 0,
			"restoreState" : 0,
			"isEOF" : 1,
			"direction" : "forward",
			"docsExamined" : 5
		}
	}
}

쿼리 최적화 아이디어

  • 가능한 한 인덱스를 사용
  • 스캔하는 문서 수를 줄일수록 좋습니다