[SERVER-86333] Avoid unnecessary fetch stage in findAndModify commands representing removals Created: 06/Feb/24  Updated: 07/Feb/24

Status: Backlog
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major - P3
Reporter: Ben Shteinfeld Assignee: Backlog - Query Optimization
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Assigned Teams:
Query Optimization
Participants:

 Description   

In the tpc-c workload, there is an index 

{
                "v" : 2,
                "key" : {
                        "NO_W_ID" : 1,
                        "NO_D_ID" : 1,
                        "NO_O_ID" : 1
                },
                "name" : "NO_W_ID_1_NO_D_ID_1_NO_O_ID_1",
                "unique" : true
        } 

and a findAndModify command,

 

{"findAndModify":"NEW_ORDER","query":{"NO_D_ID":6,"NO_W_ID":655,"$comment":"DELIVERY 6"},"new":false,"remove":true,"fields":{"_id":0,"NO_D_ID":1,"NO_W_ID":1,"NO_O_ID":1},"sort":{"NO_O_ID":1}}

which generates a plan that looks like

 

 "winningPlan" : {
                        "isCached" : false,
                        "stage" : "PROJECTION_DEFAULT",
                        "transformBy" : {
                                "_id" : 0,
                                "NO_D_ID" : 1,
                                "NO_W_ID" : 1,
                                "NO_O_ID" : 1
                        },
                        "inputStage" : {
                                "stage" : "DELETE",
                                "inputStage" : {
                                        "stage" : "LIMIT",
                                        "limitAmount" : 1,
                                        "inputStage" : {
                                                "stage" : "FETCH",
                                                "inputStage" : {
                                                        "stage" : "IXSCAN",
                                                        "keyPattern" : {
                                                                "NO_W_ID" : 1,
                                                                "NO_D_ID" : 1,
                                                                "NO_O_ID" : 1
                                                        },
                                                        "indexName" : "NO_W_ID_1_NO_D_ID_1_NO_O_ID_1",
                                                        "isMultiKey" : false,
                                                        "multiKeyPaths" : {
                                                                "NO_W_ID" : [ ],
                                                                "NO_D_ID" : [ ],
                                                                "NO_O_ID" : [ ]
                                                        },
                                                        "isUnique" : true,
                                                        "isSparse" : false,
                                                        "isPartial" : false,
                                                        "indexVersion" : 2,
                                                        "direction" : "forward",
                                                        "indexBounds" : {
                                                                "NO_W_ID" : [
                                                                        "[1.0, 1.0]"
                                                                ],
                                                                "NO_D_ID" : [
                                                                        "[6.0, 6.0]"
                                                                ],
                                                                "NO_O_ID" : [
                                                                        "[MinKey, MaxKey]"
                                                                ]
                                                        }
                                                }
                                        }
                                }
                        }
                },
                "rejectedPlans" : [ ]

The fetch above the index scan seems unnecessary since the projection can be satisfied by the index. The documentation is a bit unclear about the semantics of findAndModify, typically it will return the document it found, but if there is a covering projection, then a fetch is not required.

 

 

 


Generated at Thu Feb 08 07:00:01 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.