2. Interested in Open Source technologies
Active MongoDB Community Contributor
Tech Speaker/Blogger
Senior DevOps and MongoDB Consultant
Manosh Malai
About Me
5. MongoDB Execution Plan Analysis
MongoDB Optimizer and Plan Cache
Query in the MongoDB Execution Layer
Agenda
6. Query In The MongoDB Execution Layer
Client net listener
thread_conn
Query Decode
Operation
Context
Catalog
MapLayer
Canonical Plan
Plan Executor Optimizer
RecordStore & Cursor Snapshot
7. A client connects to MongoDB and creates a new thread to handle all requests.
Some Query(Such as insert) does not need to execute the plan, It will directly interact with the engine
through RecordStore.
Query performs simple processing (standardization) and builds some context data structures into
CanonicalQuery.
The Plan module is qualified for generating multiple execution plans for the Query, then delivering it to
the Optimizer to select the best one and surrendering it to the PlanExecutor.
PlanExecutor step by step according to the execution plan to obtain the final data (or perform the
update to modify the data).
Query Statement Execution Algorithm
8. Current version of Explain has three mode:
queryPlanner
executionStats
allPlansExecution
db.collection.find().explain()
Execution Plan Analysis
MongoDB Execution Plan Analysis
9. queryPlanner is the default mode of the current version of explain.
The queryPlanner mode does not actually query the query statement.
Performs an execution plan analysis for the query statement and selects the winning plan.
queryPlanner.winningPlan.stage: COLLSCAN
Without Index
queryPlanner.winningPlan.stage: FETCH
With Index
queryPlanner Mode
10. queryPlanner + executionStats information of the evaluated query.
With Index
explain.queryPlanner.indexFilterSet
explain.queryPlanner.winningPlan.stage
explain.executionStats.nReturned
explain.executionStats.executionTimeMillis
explain.executionStats.totalKeysExamined
explain.executionStats.totalDocsExamined
explain.executionStats.executionStages.advanced
explain.executionStats.executionStages.works
explain.executionStats.executionStages.inputStage.docsExamined
explain.executionStats.executionStages.isEOF
executionStats Mode
11. EX
db.runCommand( {
planCacheSetFilter: "orders",
query: { status: "A" },
indexes: [ { cust_id: 1, status: 1 },
{ status: 1, order_date: -1 } ]
} )
IndexFilter determines how the query
optimizer will use index for a type of
query.
Thquery optimizer will ignore the index
set by the
1. explain.queryPlanner.indexFilterSet
The stage of the optimal execution plan
2. explain.queryPlanner.winningPlan.stage
COLLSCAN: Full table scan
IXSCAN: Index scan
FETCH: Retrieve the specified document based on the indexEmpty text
SHARD_MERGE: Return each fragment to the data for merge
SORT: Indicates that sorting is done in memor
LIMIT: Use limit to limit the number of returns
SKIP: Skip using skip
IDHACK: Query for _id
SHARDING_FILTER: Querying fragmented data by mongos
COUNT: Count operation using db.coll.explain().count()
COUNTSCAN: Count does not use the stage return when using Count for
index
COUNT_SCAN: Count uses the stage to return when the index is counted
SUBPLA: Stage return of $or query not used to index
TEXT: Stage return when using full-text index for queryPROJECTION: The
return of the stage when the return field is qualified
STAGE
executionStats Metrics
12. executionStats Metrics
The number of returns returned by the query
3. explain.executionStats.nReturned
Overall execution time
4. explain.executionStats.executionTimeMillis
Number of index scans
5. explain.executionStats.totalKeysExamined
Document scans
6. explain.executionStats.totalDocsExamined
14. The planner ask plan each time for the next document via call to work()
If the plan can give supply document it respond with document, Otherwise the plan respond with
needTime
If all the all the document have been retrieved then isEOF = 1
Work - Advanced - isEOF [ Algorithm ]
"works": 18667
"advanced": 18666
"needTime": 0
15. WorkingSet workingSet;
PlanStage* rootStage = makeQueryPlan(&workingSet, ...);
while (!rootStage->isEOF()) {
WorkingSetID result;
switch(rootStage->work(&result)) {
case PlanStage::ADVANCED:
// do something with result
WorkingSetMember* member = workingSet.get(result);
cout << "Result: " << member->obj << std::endl;
break;
case PlanStage::IS_EOF:
// All done. Will fall out of while loop.
break;
Work - Advanced - isEOF [ Code ]
Cont . .
case PlanStage::NEED_TIME:
// Need more time.
break;
case PlanStage::FAILURE:
// Throw exception or return error.
break;
}
if (shouldYield) {
// Occasionally yield.
stage->saveState();
stage->restoreState();
}
}
16. As the name suggests, the allPlanExxecution mode is to perform all
execution plans in the executionStats mode. It will show all candidate
Rejected Plans.
allPlansExecution Mode
18. Find Matching
Cache Entry
Empty
text
Evaluate Plan
Performance
Generate
Candidate Plans
Query
Empty
text
Evaluate
Candidate Plans
Choose Winning
Plans
Create Cache
Entry
Generate Result
Documents
Evict Cache
Entry
NO MATCH
MATCH
FAIL
PASS
Plan Optimiser
19. QueryPlanner Canonical Query
Canonical Query * No of Indexes based on
predicate Conditions = Candidate Plane
Select a Wining Plane and Add it Plane Cache
Ranking the Candidate Plane
23. numWorks - Advanced Work Units
Query Returns 102
document
no of document <= 101YES NO
numWorks = 101
numWorks = no of
document
advanced =
numWorks
works = numWorks
+ 1
advanced =
numWorks
works = numWorks
25. Index Re-build will evict the plan cache
Add or Delete Index will evict the plan cache
The MongoD process restart will evict the plan cache
internalQueryCacheEvictionRatio * _decisionWorks will do
the plan cache eviction
MongoDB Plan Cache - Eviction
internalQueryCacheEvictionRatio: 10.0
_decisionWorks: The number of work cycles taken to decide on
a winning plan when the plan was first