diff options
author | Ian Boros <ian.boros@mongodb.com> | 2021-05-27 17:08:35 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-06-01 17:42:46 +0000 |
commit | 90eb445e58124ed8b6b46a048834bffe350dad4c (patch) | |
tree | cc24fb680e254f1e4eff5946b51b7b924af8d561 | |
parent | abda02c1aa43b6ce053eb8857d1724dceee43fd2 (diff) | |
download | mongo-90eb445e58124ed8b6b46a048834bffe350dad4c.tar.gz |
SERVER-57225 Prevent top-level AND optimization from being used for ANDs with many children
-rw-r--r-- | jstests/core/big_predicate.js | 20 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder_filter.cpp | 7 |
2 files changed, 25 insertions, 2 deletions
diff --git a/jstests/core/big_predicate.js b/jstests/core/big_predicate.js new file mode 100644 index 00000000000..d9d140b31d8 --- /dev/null +++ b/jstests/core/big_predicate.js @@ -0,0 +1,20 @@ +/** + * Test that a query containing an AND with a lot of clauses can be answered. + */ +(function() { +"use strict"; + +const coll = db.big_predicate; +coll.drop(); + +let filter = {}; +for (let i = 0; i < 2500; ++i) { + filter["field" + i] = 123; +} + +assert.commandWorked(coll.insert({foo: 1})); +assert.commandWorked(coll.insert(filter)); + +assert.eq(coll.find(filter).itcount(), 1); +assert.commandWorked(coll.explain().find(filter).finish()); +})(); diff --git a/src/mongo/db/query/sbe_stage_builder_filter.cpp b/src/mongo/db/query/sbe_stage_builder_filter.cpp index 0cdccc4323a..cedb52a3f5b 100644 --- a/src/mongo/db/query/sbe_stage_builder_filter.cpp +++ b/src/mongo/db/query/sbe_stage_builder_filter.cpp @@ -80,6 +80,7 @@ namespace mongo::stage_builder { namespace { struct MatchExpressionVisitorContext; +const size_t kMaxChildrenForTopLevelAndOptimization = 25; /** * Output of the tree can come from two places: @@ -131,7 +132,8 @@ struct MatchExpressionVisitorContext { // If the root node is an $and, store it in 'topLevelAnd'. // TODO: SERVER-50673: Revisit how we implement the top-level $and optimization. - if (root->matchType() == MatchExpression::AND) { + if (root->matchType() == MatchExpression::AND && + root->numChildren() <= kMaxChildrenForTopLevelAndOptimization) { topLevelAnd = root; } } @@ -165,7 +167,8 @@ struct MatchExpressionVisitorContext { // If the root node is an $and, store it in 'topLevelAnd'. // TODO: SERVER-50673: Revisit how we implement the top-level $and optimization. - if (root->matchType() == MatchExpression::AND) { + if (root->matchType() == MatchExpression::AND && + root->numChildren() <= kMaxChildrenForTopLevelAndOptimization) { topLevelAnd = root; } } |