AWS documentdb documentation change
Summary
Added comprehensive documentation section 'Understanding docsExamined in Explain Plan Execution Stats' with detailed explanations, field descriptions, stage breakdowns, and multiple query examples showing how docsExamined metrics work in Amazon DocumentDB 8.0.0+.
Security assessment
This change adds performance optimization documentation about query plan analysis metrics (docsExamined, totalDocsExamined) to help developers identify inefficient queries. There is no evidence of addressing security vulnerabilities, weaknesses, or incidents. The documentation focuses on query performance tuning rather than security features.
Diff
diff --git a/documentdb/latest/developerguide/performance-query-plan-analysis.md b/documentdb/latest/developerguide/performance-query-plan-analysis.md index 6e714889f..441598586 100644 --- a//documentdb/latest/developerguide/performance-query-plan-analysis.md +++ b//documentdb/latest/developerguide/performance-query-plan-analysis.md @@ -7 +7 @@ -Overall TimingExecution Stages +Overall TimingExecution StagesUnderstanding docsExamined in Explain Plan Execution Stats @@ -11 +11 @@ Overall TimingExecution Stages -Query plan analysis through explain plan provides essential insights into Amazon Amazon DocumentDB query performance. Query plan with executionStats reveals key metrics including: +Query plan analysis through explain plan provides essential insights into Amazon DocumentDB query performance. Query plan with executionStats reveals key metrics including: @@ -110 +110 @@ planningTimeMillis represents the total planning time taken by the query. -It describes the step-by-step process Amazon Amazon DocumentDB uses to execute a query, showing how data flows through different operations. +It describes the step-by-step process Amazon DocumentDB uses to execute a query, showing how data flows through different operations. @@ -189,0 +190,290 @@ The executionStats parameter does not currently support update and delete comman +## Understanding docsExamined in Explain Plan Execution Stats + +When you run a query with `explain("executionStats")`, Amazon DocumentDB provides examination metrics that help you understand how many documents were scanned to produce the query results. These metrics are useful for identifying inefficient query plans and optimizing performance. + +###### Note + +Available only in Amazon DocumentDB 8.0.0+. + +### Fields + +Field | Description | Level +---|---|--- +totalDocsExamined | Total number of documents examined across all execution stages. | Top-level executionStats +docsExamined | Number of documents examined by a specific execution stage. | Stage-level + +The `docsExamined` field appears on the following stages: + +Stage | Description +---|--- +COLLSCAN | Collection scan. All documents in the collection are examined. +IXSCAN | Index scan. Only documents matching the index condition are examined. +FETCH | When the optimizer retrieves documents in a separate stage from IXSCAN, the FETCH stage reports docsExamined. In index scan plans, the child IXSCAN stages do not report docsExamined. In $lookup plans, both the FETCH stage and its child stages may report docsExamined. + +###### Note + +`docsExamined` does not appear on IXONLYSCAN stages because the query is satisfied entirely from the index without accessing documents. + +### Show docsExamined in Explain Plan executionStats Output + +The following examples use a collection with 500,000 documents and demonstrate how `docsExamined` changes across different query execution stages. + +Create sample data: + + + for (let i = 0; i < 500000; i++) { + db.coll.insertOne({ number: i, arr: [i, [i+1]], value: "test", bool: i % 2 === 0 }); + } + + +#### Collection Scan (COLLSCAN) + +Without an index, Amazon DocumentDB performs a full collection scan. + + + db.coll.find({ "number": { "$lt": 500 } }).explain("executionStats").executionStats + + +Output: + + + { + "executionSuccess" : true, + "nReturned" : "500", + "executionTimeMillis" : "282.055", + "planningTimeMillis" : "0.085", + "totalDocsExamined" : "500000", + "executionStages" : { + "stage" : "COLLSCAN", + "nReturned" : "500", + "executionTimeMillisEstimate" : "281.915", + "docsExamined" : "500000", + "filter" : { + "number" : { + "$lt" : 500 + } + } + } + } + + +All 500,000 documents were examined to return 500 results. Creating an index on the number field improves this. + +#### Index Scan (IXSCAN) + + + db.coll.createIndex({ number: 1 }); + db.coll.find({ "number": { "$lt": 5000 } }).explain("executionStats").executionStats + + +Output: + + + { + "executionSuccess" : true, + "nReturned" : "5000", + "executionTimeMillis" : "3.047", + "planningTimeMillis" : "0.296", + "totalDocsExamined" : "5000", + "executionStages" : { + "stage" : "IXSCAN", + "nReturned" : "5000", + "executionTimeMillisEstimate" : "2.576", + "indexName" : "number_1", + "direction" : "forward", + "docsExamined" : "5000", + "indexCond" : { + "$and" : [ + { + "number" : { + "$lt" : 5000 + } + } + ] + } + } + } + + +With the index, only 5,000 out of 500,000 documents were examined and fetched, matching the number returned. The index condition filtered out 495,000 documents that did not match the query. + +#### Index Scan with Residual Filter + + + db.coll.find({ "number": { "$lt": 5000 }, "arr": { "$gt": 4000 } }).explain("executionStats").executionStats + + +Output: + + + { + "executionSuccess" : true, + "nReturned" : "999", + "executionTimeMillis" : "15.367", + "planningTimeMillis" : "0.115", + "totalDocsExamined" : "5000", + "executionStages" : { + "stage" : "IXSCAN", + "nReturned" : "999", + "executionTimeMillisEstimate" : "15.170", + "indexName" : "number_1", + "direction" : "forward", + "docsExamined" : "5000", + "indexCond" : { + "$and" : [ + { + "number" : { + "$lt" : 5000 + } + } + ] + }, + "filter" : { + "arr" : { + "$gt" : 4000 + } + } + } + } + + +The index condition matched 5,000 documents out of 500,000, then the residual filter on `arr` reduced the result to 999. The `docsExamined` value of 5,000 reflects all documents examined after the index condition but before the residual filter was applied. + +#### Fetch with IXSCAN + + + db.coll.find({ "$or": [{ "number": { "$lt": 100000 } }, { "number": { "$gt": 400000 } }] }).explain("executionStats").executionStats + + +Output: + + + { + "executionSuccess" : true, + "nReturned" : "199999", + "executionTimeMillis" : "899.801", + "planningTimeMillis" : "0.183", + "totalDocsExamined" : "199999", + "executionStages" : { + "stage" : "FETCH", + "nReturned" : "199999", + "executionTimeMillisEstimate" : "894.141", + "docsExamined" : "199999", + "inputStage" : { + "stage" : "IXOR", + "nReturned" : "0", + "executionTimeMillisEstimate" : "874.897", + "inputStages" : [ + { + "stage" : "IXSCAN", + "nReturned" : "100000", + "executionTimeMillisEstimate" : "462.208", + "indexName" : "number_1", + "indexCond" : { + "$and" : [ + { + "number" : {