summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@mongodb.com>2022-07-14 18:09:12 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-07-14 19:16:56 +0000
commit5dfda9e29d70115f1af249d540b414ad8227834a (patch)
treec2340734a5ab04e57ddc1d950d8ac4994cfb4039
parent91cef76e80b79fe4a2867413af5910027c3b69d5 (diff)
downloadmongo-5dfda9e29d70115f1af249d540b414ad8227834a.tar.gz
SERVER-61314 Consolidate featureFlagSbePlanCache with featureFlagSbeFull
-rw-r--r--jstests/core/collation_plan_cache.js5
-rw-r--r--jstests/core/explode_for_sort_plan_cache.js2
-rw-r--r--jstests/core/idhack.js5
-rw-r--r--jstests/core/index_filter_commands_invalidate_plan_cache_entries.js11
-rw-r--r--jstests/core/plan_cache_list_plans.js6
-rw-r--r--jstests/core/plan_cache_list_shapes.js4
-rw-r--r--jstests/core/plan_cache_sbe.js30
-rw-r--r--jstests/core/plan_cache_shell_helpers.js5
-rw-r--r--jstests/core/query_hash_stability.js2
-rw-r--r--jstests/core/sbe/plan_cache_sbe_with_or_queries.js5
-rw-r--r--jstests/core/sbe_plan_cache_autoparameterize_collscan.js8
-rw-r--r--jstests/core/wildcard_index_cached_plans.js37
-rw-r--r--jstests/core/wildcard_index_filter.js6
-rw-r--r--jstests/noPassthrough/plan_cache_group_lookup.js29
-rw-r--r--jstests/noPassthrough/plan_cache_index_create.js4
-rw-r--r--jstests/noPassthrough/plan_cache_list_failed_plans.js12
-rw-r--r--jstests/noPassthrough/plan_cache_memory_debug_info.js4
-rw-r--r--jstests/noPassthrough/plan_cache_replan_group_lookup.js41
-rw-r--r--jstests/noPassthrough/plan_cache_replan_sort.js2
-rw-r--r--jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js8
-rw-r--r--jstests/noPassthrough/sbe_plan_cache_key_reporting.js4
-rw-r--r--jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js4
-rw-r--r--jstests/noPassthrough/sbe_plan_cache_size_metric.js122
-rw-r--r--jstests/noPassthroughWithMongod/index_bounds_static_limit.js26
-rw-r--r--jstests/noPassthroughWithMongod/ne_array_indexability.js2
-rw-r--r--jstests/noPassthroughWithMongod/plan_cache_replanning.js11
-rw-r--r--src/mongo/db/commands/index_filter_commands.cpp4
-rw-r--r--src/mongo/db/commands/plan_cache_clear_command.cpp4
-rw-r--r--src/mongo/db/exec/plan_cache_util.cpp2
-rw-r--r--src/mongo/db/exec/plan_cache_util.h7
-rw-r--r--src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp2
-rw-r--r--src/mongo/db/query/canonical_query.cpp6
-rw-r--r--src/mongo/db/query/canonical_query_encoder.cpp4
-rw-r--r--src/mongo/db/query/canonical_query_encoder_test.cpp6
-rw-r--r--src/mongo/db/query/canonical_query_test.cpp4
-rw-r--r--src/mongo/db/query/explain.cpp2
-rw-r--r--src/mongo/db/query/get_executor.cpp11
-rw-r--r--src/mongo/db/query/query_feature_flags.idl8
-rw-r--r--src/mongo/db/query/sbe_cached_solution_planner.cpp9
-rw-r--r--src/mongo/db/query/sbe_plan_cache.cpp16
-rw-r--r--src/mongo/db/query/sbe_stage_builder_filter.cpp22
41 files changed, 224 insertions, 278 deletions
diff --git a/jstests/core/collation_plan_cache.js b/jstests/core/collation_plan_cache.js
index 8f108a89b9e..88a54798642 100644
--- a/jstests/core/collation_plan_cache.js
+++ b/jstests/core/collation_plan_cache.js
@@ -14,8 +14,7 @@
load("jstests/libs/analyze_plan.js"); // For getPlanCacheKeyFromExplain.
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-const isSbePlanCacheEnabled =
- checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]);
+const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
var coll = db.collation_plan_cache;
coll.drop();
@@ -49,7 +48,7 @@ assert.commandWorked(
// The query shape should have been added.
var shapes = coll.aggregate([{$planCacheStats: {}}]).toArray();
assert.eq(1, shapes.length, 'unexpected cache size after running query');
-if (!isSbePlanCacheEnabled) {
+if (!isSbeEnabled) {
assert.eq(shapes[0].createdFromQuery.query, {a: 'foo', b: 5}, shapes);
assert.eq(shapes[0].createdFromQuery.sort, {}, shapes);
assert.eq(shapes[0].createdFromQuery.projection, {}, shapes);
diff --git a/jstests/core/explode_for_sort_plan_cache.js b/jstests/core/explode_for_sort_plan_cache.js
index f4e5a87be7f..7a3935ce233 100644
--- a/jstests/core/explode_for_sort_plan_cache.js
+++ b/jstests/core/explode_for_sort_plan_cache.js
@@ -56,7 +56,7 @@ const sortSpec = {
// TODO SERVER-67576: remove this branch once explode for sort plans are supported by the SBE plan
// cache.
-if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
+if (checkSBEEnabled(db, ["featureFlagSbeFull"])) {
// Run the query for the first time and make sure the plan hasn't been cached.
assert.eq(0, coll.find(querySpec).sort(sortSpec).itcount());
assertCacheEntryDoesNotExist(querySpec, sortSpec);
diff --git a/jstests/core/idhack.js b/jstests/core/idhack.js
index ff541a59c0f..69c157221e0 100644
--- a/jstests/core/idhack.js
+++ b/jstests/core/idhack.js
@@ -62,9 +62,8 @@ winningPlan = getWinningPlan(explain.queryPlanner);
engineSpecificAssertion(!isIdhack(db, winningPlan), isIxscan(db, winningPlan), db, winningPlan);
// Covered query returning _id field only can be handled by ID hack.
-const isSBEPlanCacheEnabled =
- checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]);
-const parentStage = isSBEPlanCacheEnabled ? "PROJECTION_COVERED" : "FETCH";
+const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
+const parentStage = isSbeEnabled ? "PROJECTION_COVERED" : "FETCH";
explain = t.find(query, {_id: 1}).explain();
winningPlan = getWinningPlan(explain.queryPlanner);
engineSpecificAssertion(
diff --git a/jstests/core/index_filter_commands_invalidate_plan_cache_entries.js b/jstests/core/index_filter_commands_invalidate_plan_cache_entries.js
index e4011c61198..37f23dc96d4 100644
--- a/jstests/core/index_filter_commands_invalidate_plan_cache_entries.js
+++ b/jstests/core/index_filter_commands_invalidate_plan_cache_entries.js
@@ -17,10 +17,9 @@
load("jstests/libs/analyze_plan.js"); // For getPlanCacheKeyFromShape.
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-// For testing convenience this variable is made an integer "1" if featureFlagSbePlanCache is on,
-// because the expected amount of plan cache entries differs between the two different plan caches.
-const isSbePlanCacheEnabled =
- checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]) ? 1 : 0;
+// For testing convenience this variable is made an integer "1" if SBE is fully enabled, because the
+// expected amount of plan cache entries differs between the SBE plan cache and the classic one.
+const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]) ? 1 : 0;
const collName = "index_filter_commands_invalidate_plan_cache_entries";
const coll = db[collName];
@@ -61,11 +60,11 @@ assert.eq(0, coll.find({a: 1}).skip(1).itcount());
// SBE plan cache key encodes "skip", so there's one more plan cache entry in SBE plan cache. While
// in classic plan cache, queries with only difference in "skip" share the same plan cache entry.
-assert.eq(coll.aggregate([{$planCacheStats: {}}]).itcount(), 3 + isSbePlanCacheEnabled);
+assert.eq(coll.aggregate([{$planCacheStats: {}}]).itcount(), 3 + isSbeEnabled);
assert.commandWorked(
db.runCommand({planCacheSetFilter: collName, query: {a: 1, b: 1}, indexes: [{a: 1}]}));
-assert.eq(coll.aggregate([{$planCacheStats: {}}]).toArray().length, 2 + isSbePlanCacheEnabled);
+assert.eq(coll.aggregate([{$planCacheStats: {}}]).toArray().length, 2 + isSbeEnabled);
// This planCacheSetFilter command will invalidate plan cache entries with filter {a: 1}. There are
// two entries in the SBE plan cache that got invalidated, or one entry in the classic plan cache
diff --git a/jstests/core/plan_cache_list_plans.js b/jstests/core/plan_cache_list_plans.js
index e478be751da..02a1d71593c 100644
--- a/jstests/core/plan_cache_list_plans.js
+++ b/jstests/core/plan_cache_list_plans.js
@@ -24,7 +24,7 @@ load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
let coll = db.jstests_plan_cache_list_plans;
coll.drop();
-const isSBEAndPlanCacheOn = checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]);
+const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
function dumpPlanCacheState() {
return coll.aggregate([{$planCacheStats: {}}]).toArray();
@@ -94,7 +94,7 @@ let entry = getPlansForCacheEntry({a: 1, b: 1}, {a: -1}, {_id: 0, a: 1});
assert(entry.hasOwnProperty('works'), entry);
assert.eq(entry.isActive, false);
-if (!isSBEAndPlanCacheOn) {
+if (!isSbeEnabled) {
// Note that SBE plan cache entry does not include "creationExecStats". We expect that there
// were two candidate plans evaluated when the cache entry was created.
assert(entry.hasOwnProperty("creationExecStats"), entry);
@@ -131,7 +131,7 @@ entry = getPlansForCacheEntry({a: 3, b: 3}, {a: -1}, {_id: 0, a: 1});
assert(entry.hasOwnProperty('works'), entry);
assert.eq(entry.isActive, true);
-if (!isSBEAndPlanCacheOn) {
+if (!isSbeEnabled) {
// Note that SBE plan cache entry does not include "creationExecStats". There should be the same
// number of candidate plan scores as candidate plans.
assert.eq(entry.creationExecStats.length, entry.candidatePlanScores.length, entry);
diff --git a/jstests/core/plan_cache_list_shapes.js b/jstests/core/plan_cache_list_shapes.js
index 83dd402cbbb..6db043884bf 100644
--- a/jstests/core/plan_cache_list_shapes.js
+++ b/jstests/core/plan_cache_list_shapes.js
@@ -16,8 +16,8 @@
'use strict';
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE and SBE plan cache are both enabled.");
+if (checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+ jsTest.log("Skipping test because SBE is fully enabled.");
return;
}
diff --git a/jstests/core/plan_cache_sbe.js b/jstests/core/plan_cache_sbe.js
index 6ca74ad42f3..723b96abc54 100644
--- a/jstests/core/plan_cache_sbe.js
+++ b/jstests/core/plan_cache_sbe.js
@@ -19,18 +19,16 @@
(function() {
"use strict";
-load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-load("jstests/libs/sbe_explain_helpers.js"); // For engineSpecificAssertion.
+load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
const coll = db.plan_cache_sbe;
coll.drop();
-const isSbePlanCacheEnabled =
- checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]);
+const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
assert.commandWorked(coll.insert({a: 1, b: 1}));
// Check that a new entry is added to the plan cache even for single plans.
-if (isSbePlanCacheEnabled) {
+if (isSbeEnabled) {
assert.eq(1, coll.find({a: 1}).itcount());
// Validate sbe plan cache stats entry.
const allStats = coll.aggregate([{$planCacheStats: {}}]).toArray();
@@ -56,23 +54,11 @@ assert.eq(allStats.length, 1, allStats);
const stats = allStats[0];
assert(stats.hasOwnProperty("cachedPlan"), stats);
-if (!isSbePlanCacheEnabled) {
- // TODO SERVER-61314: Please modify this branch when "featureFlagSbePlanCache" is removed.
- // Currently this branch will be taken if either 1) SBE is disabled, or 2) SBE is enabled but
- // the "featureFlagSbePlanCache" flag is disabled.
- engineSpecificAssertion(!stats.cachedPlan.hasOwnProperty("queryPlan"),
- stats.cachedPlan.hasOwnProperty("queryPlan"),
- db,
- stats);
- engineSpecificAssertion(!stats.cachedPlan.hasOwnProperty("slotBasedPlan"),
- stats.cachedPlan.hasOwnProperty("slotBasedPlan"),
- db,
- stats);
+if (isSbeEnabled) {
+ assert(stats.cachedPlan.hasOwnProperty("slots"), stats);
+ assert(stats.cachedPlan.hasOwnProperty("stages"), stats);
} else {
- engineSpecificAssertion(
- !stats.cachedPlan.hasOwnProperty("slots") && !stats.cachedPlan.hasOwnProperty("stages"),
- stats.cachedPlan.hasOwnProperty("slots") && stats.cachedPlan.hasOwnProperty("stages"),
- db,
- stats);
+ assert(!stats.cachedPlan.hasOwnProperty("queryPlan"), stats);
+ assert(!stats.cachedPlan.hasOwnProperty("slotBasedPlan"), stats);
}
})();
diff --git a/jstests/core/plan_cache_shell_helpers.js b/jstests/core/plan_cache_shell_helpers.js
index 299f071e8d9..1628883aaa2 100644
--- a/jstests/core/plan_cache_shell_helpers.js
+++ b/jstests/core/plan_cache_shell_helpers.js
@@ -17,8 +17,7 @@ load('jstests/aggregation/extras/utils.js'); // For assertArrayEq.
load("jstests/libs/analyze_plan.js"); // For getPlanCacheKeyFromShape.
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-const isSBEPlanCacheEnabled =
- checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]);
+const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
var coll = db.jstests_plan_cache_shell_helpers;
coll.drop();
@@ -81,7 +80,7 @@ assert.eq([{count: 4}], planCache.list([{$count: "count"}]), planCache.list());
// Test that we can collect descriptions of all the queries that created cache entries using the
// list() helper.
-if (isSBEPlanCacheEnabled) {
+if (isSbeEnabled) {
assertArrayEq({
expected: [
{planCacheKey: getPlanCacheKeyFromShape({query: queryB, collection: coll, db: db})},
diff --git a/jstests/core/query_hash_stability.js b/jstests/core/query_hash_stability.js
index 129c8a4c701..aa0a3399e70 100644
--- a/jstests/core/query_hash_stability.js
+++ b/jstests/core/query_hash_stability.js
@@ -112,7 +112,7 @@ assertPlanCacheField({
// SBE's planCacheKey encoding encodes "collection version" which will be increased after dropping
// an index.
-if (!checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
+if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
// The 'planCacheKey' should be the same as what it was before we dropped the index.
assertPlanCacheField({
firstExplain: initialExplain,
diff --git a/jstests/core/sbe/plan_cache_sbe_with_or_queries.js b/jstests/core/sbe/plan_cache_sbe_with_or_queries.js
index f5e61d19110..a529af6e23c 100644
--- a/jstests/core/sbe/plan_cache_sbe_with_or_queries.js
+++ b/jstests/core/sbe/plan_cache_sbe_with_or_queries.js
@@ -16,9 +16,8 @@
load("jstests/libs/analyze_plan.js");
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-const isSBEEnabled = checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]);
-if (!isSBEEnabled) {
- jsTest.log("Skip running the test because featureFlagSbePlanCache is not enabled");
+if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+ jsTest.log("Skip running the test because SBE is not enabled");
return;
}
diff --git a/jstests/core/sbe_plan_cache_autoparameterize_collscan.js b/jstests/core/sbe_plan_cache_autoparameterize_collscan.js
index 63054ff7d7d..05c188a04a5 100644
--- a/jstests/core/sbe_plan_cache_autoparameterize_collscan.js
+++ b/jstests/core/sbe_plan_cache_autoparameterize_collscan.js
@@ -17,10 +17,10 @@
load("jstests/libs/analyze_plan.js");
load("jstests/libs/sbe_util.js");
-// This test is specifically verifying the behavior of the SBE plan cache. So if either the SBE plan
-// cache or SBE itself are disabled, bail out.
-if (!checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
- jsTestLog("Skipping test because either SBE engine or SBE plan cache is disabled");
+// This test is specifically verifying the behavior of the SBE plan cache, which is only enabled
+// when 'featureFlagSbeFull' is on.
+if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+ jsTestLog("Skipping test because SBE is not fully enabled");
return;
}
diff --git a/jstests/core/wildcard_index_cached_plans.js b/jstests/core/wildcard_index_cached_plans.js
index 9b0b0c33b6d..586882381e9 100644
--- a/jstests/core/wildcard_index_cached_plans.js
+++ b/jstests/core/wildcard_index_cached_plans.js
@@ -19,9 +19,8 @@
load('jstests/libs/analyze_plan.js'); // For getPlanStage().
load("jstests/libs/collection_drop_recreate.js"); // For assert[Drop|Create]Collection.
-load('jstests/libs/fixture_helpers.js'); // For getPrimaryForNodeHostingDatabase and isMongos.
-load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-load("jstests/libs/sbe_explain_helpers.js"); // For engineSpecificAssertion.
+load('jstests/libs/fixture_helpers.js'); // For getPrimaryForNodeHostingDatabase and isMongos.
+load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
const coll = db.wildcard_cached_plans;
coll.drop();
@@ -29,7 +28,7 @@ coll.drop();
assert.commandWorked(coll.createIndex({"b.$**": 1}));
assert.commandWorked(coll.createIndex({"a": 1}));
-const sbePlanCacheEnabled = checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]);
+const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
// In order for the plan cache to be used, there must be more than one plan available. Insert
// data into the collection such that the b.$** index will be far more selective than the index
@@ -72,22 +71,11 @@ for (let i = 0; i < 2; i++) {
let cacheEntry = getCacheEntryForQuery(query);
assert.neq(cacheEntry, null);
assert.eq(cacheEntry.isActive, true);
-if (!sbePlanCacheEnabled) {
+if (!isSbeEnabled) {
// Should be at least two plans: one using the {a: 1} index and the other using the b.$** index.
assert.gte(cacheEntry.creationExecStats.length, 2, tojson(cacheEntry.plans));
- // In SBE index scan stage does not serialize key pattern in execution stats, so we use IXSCAN
- // from the query plan instead.
- const sbeIxScan = function() {
- const cachedPlan = cacheEntry.cachedPlan;
- if (!cachedPlan)
- return null;
- if (!cachedPlan.queryPlan)
- return null;
- return getPlanStage(cachedPlan.queryPlan, "IXSCAN");
- }();
-
- const classicIxScan = function() {
+ const ixscan = function() {
const execStats = cacheEntry.creationExecStats;
if (!execStats)
return null;
@@ -99,11 +87,14 @@ if (!sbePlanCacheEnabled) {
return getPlanStage(elem.executionStages, "IXSCAN");
}();
const expectedKeyPattern = {"$_path": 1, "b": 1};
- const classicKeyPatternMatch =
- classicIxScan !== null && bsonWoCompare(classicIxScan.keyPattern, expectedKeyPattern) === 0;
- const sbeKeyPatternmatch =
- sbeIxScan !== null && bsonWoCompare(sbeIxScan.keyPattern, expectedKeyPattern) === 0;
- engineSpecificAssertion(classicKeyPatternMatch, sbeKeyPatternmatch, db, tojson(cacheEntry));
+ assert.neq(null, ixscan, cacheEntry);
+ assert(bsonWoCompare(ixscan.keyPattern, expectedKeyPattern) === 0, ixscan);
+} else {
+ assert(cacheEntry.hasOwnProperty("cachedPlan"), cacheEntry);
+ assert(cacheEntry.cachedPlan.hasOwnProperty("stages"), cacheEntry);
+ const sbePlan = cacheEntry.cachedPlan.stages;
+ // The SBE plan string should contain the name of the b.$** index.
+ assert(sbePlan.includes("b.$**_1"), cacheEntry);
}
// Run the query again. This time it should use the cached plan. We should get the same result
@@ -125,7 +116,7 @@ assert.neq(getPlanCacheKeyFromShape({query: queryWithBNull, collection: coll, db
// There should only have been one solution for the above query, so it would get cached only by the
// SBE plan cache.
cacheEntry = getCacheEntryForQuery({a: 1, b: null});
-if (sbePlanCacheEnabled) {
+if (isSbeEnabled) {
assert.neq(cacheEntry, null);
assert.eq(cacheEntry.isActive, true, cacheEntry);
assert.eq(cacheEntry.isPinned, true, cacheEntry);
diff --git a/jstests/core/wildcard_index_filter.js b/jstests/core/wildcard_index_filter.js
index e4f06a30fc7..414b46ef1dc 100644
--- a/jstests/core/wildcard_index_filter.js
+++ b/jstests/core/wildcard_index_filter.js
@@ -12,12 +12,6 @@
load("jstests/libs/analyze_plan.js");
load("jstests/libs/fixture_helpers.js"); // For 'isMongos()'.
-load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-
-if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE and SBE plan cache are both enabled.");
- return;
-}
const coll = db.wildcard_index_filter;
diff --git a/jstests/noPassthrough/plan_cache_group_lookup.js b/jstests/noPassthrough/plan_cache_group_lookup.js
index 22d5b90fc28..88b84dd1def 100644
--- a/jstests/noPassthrough/plan_cache_group_lookup.js
+++ b/jstests/noPassthrough/plan_cache_group_lookup.js
@@ -19,7 +19,6 @@ if (!checkSBEEnabled(db)) {
}
const sbeFullEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
-const sbePlanCacheEnabled = checkSBEEnabled(db, ["featureFlagSbePlanCache"]);
assert.commandWorked(coll.insert({a: 1}));
assert.commandWorked(coll.createIndex({a: 1, a1: 1}));
@@ -102,7 +101,7 @@ const groupStage = {
(function testLoweredPipelineCombination() {
setupForeignColl();
- const expectedVersion = sbePlanCacheEnabled ? 2 : 1;
+ const expectedVersion = sbeFullEnabled ? 2 : 1;
coll.getPlanCache().clear();
testLoweredPipeline(
@@ -126,14 +125,13 @@ const groupStage = {
setupForeignColl();
testLoweredPipeline({
pipeline: [multiPlanningQueryStage, lookupStage, {$_internalInhibitOptimization: {}}],
- version: sbePlanCacheEnabled ? 2 : 1
+ version: sbeFullEnabled ? 2 : 1
});
})();
(function testNonExistentForeignCollectionCache() {
- if (!sbePlanCacheEnabled) {
- jsTestLog(
- "Skipping testNonExistentForeignCollectionCache when SBE plan cache is not enabled");
+ if (!sbeFullEnabled) {
+ jsTestLog("Skipping testNonExistentForeignCollectionCache when SBE is not fully enabled");
return;
}
@@ -156,9 +154,9 @@ const groupStage = {
})();
(function testForeignCollectionDropCacheInvalidation() {
- if (!sbePlanCacheEnabled) {
+ if (!sbeFullEnabled) {
jsTestLog(
- "Skipping testForeignCollectionDropCacheInvalidation when SBE plan cache is not enabled");
+ "Skipping testForeignCollectionDropCacheInvalidation when SBE is not fully enabled");
return;
}
@@ -171,9 +169,8 @@ const groupStage = {
})();
(function testForeignIndexDropCacheInvalidation() {
- if (!sbePlanCacheEnabled) {
- jsTestLog(
- "Skipping testForeignIndexDropCacheInvalidation when SBE plan cache is not enabled");
+ if (!sbeFullEnabled) {
+ jsTestLog("Skipping testForeignIndexDropCacheInvalidation when SBE is not fully enabled");
return;
}
@@ -186,9 +183,8 @@ const groupStage = {
})();
(function testForeignIndexBuildCacheInvalidation() {
- if (!sbePlanCacheEnabled) {
- jsTestLog(
- "Skipping testForeignIndexBuildCacheInvalidation when SBE plan cache is not enabled");
+ if (!sbeFullEnabled) {
+ jsTestLog("Skipping testForeignIndexBuildCacheInvalidation when SBE is not fully enabled");
return;
}
@@ -201,9 +197,8 @@ const groupStage = {
})();
(function testLookupSbeAndClassicPlanCacheKey() {
- if (!sbeFullEnabled || !sbePlanCacheEnabled) {
- jsTestLog(
- "Skipping testLookupWithClassicPlanCache when SBE full or SBE plan cache is not enabled");
+ if (!sbeFullEnabled) {
+ jsTestLog("Skipping testLookupWithClassicPlanCache when SBE is not fully enabled");
return;
}
diff --git a/jstests/noPassthrough/plan_cache_index_create.js b/jstests/noPassthrough/plan_cache_index_create.js
index 862a46b7c64..26d6c1d8bb7 100644
--- a/jstests/noPassthrough/plan_cache_index_create.js
+++ b/jstests/noPassthrough/plan_cache_index_create.js
@@ -178,8 +178,8 @@ rst.initiate();
const primaryDB = rst.getPrimary().getDB(dbName);
const secondaryDB = rst.getSecondary().getDB(dbName);
-if (checkSBEEnabled(primaryDB, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE and SBE plan cache are both enabled.");
+if (checkSBEEnabled(primaryDB, ["featureFlagSbeFull"])) {
+ jsTest.log("Skipping test because SBE is fully enabled");
rst.stopSet();
return;
}
diff --git a/jstests/noPassthrough/plan_cache_list_failed_plans.js b/jstests/noPassthrough/plan_cache_list_failed_plans.js
index 853680f1872..9fd79e8308e 100644
--- a/jstests/noPassthrough/plan_cache_list_failed_plans.js
+++ b/jstests/noPassthrough/plan_cache_list_failed_plans.js
@@ -8,10 +8,9 @@ const conn = MongoRunner.runMongod();
assert.neq(null, conn, "mongod was unable to start up");
const testDB = conn.getDB("jstests_plan_cache_list_failed_plans");
const coll = testDB.test;
-const isSBEEnabled = checkSBEEnabled(testDB, ["featureFlagSbeFull"]);
-if (checkSBEEnabled(testDB, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE and SBE plan cache are both enabled.");
+if (checkSBEEnabled(testDB, ["featureFlagSbeFull"])) {
+ jsTest.log("Skipping test because SBE is fully enabled");
MongoRunner.stopMongod(conn);
return;
}
@@ -44,12 +43,7 @@ const creationExecStats = planCacheEntry.creationExecStats;
assert.eq(creationExecStats.length, 2, planCacheEntry);
// We expect that the first plan succeed, and the second failed.
assert(!creationExecStats[0].hasOwnProperty("failed"), planCacheEntry);
-// SBE will not report the 'failed' field.
-if (isSBEEnabled) {
- assert(!creationExecStats[1].hasOwnProperty("failed"), planCacheEntry);
-} else {
- assert.eq(creationExecStats[1].failed, true, planCacheEntry);
-}
+assert.eq(creationExecStats[1].failed, true, planCacheEntry);
// The failing plan should have a score of 0.
const candidatePlanScores = planCacheEntry.candidatePlanScores;
diff --git a/jstests/noPassthrough/plan_cache_memory_debug_info.js b/jstests/noPassthrough/plan_cache_memory_debug_info.js
index e7c36ac4fff..dc126dcc2b0 100644
--- a/jstests/noPassthrough/plan_cache_memory_debug_info.js
+++ b/jstests/noPassthrough/plan_cache_memory_debug_info.js
@@ -79,8 +79,8 @@ assert.neq(conn, null, "mongod failed to start");
const db = conn.getDB("test");
const coll = db.plan_cache_memory_debug_info;
-if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE and SBE plan cache are both enabled.");
+if (checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+ jsTest.log("Skipping test because SBE is fully enabled");
MongoRunner.stopMongod(conn);
return;
}
diff --git a/jstests/noPassthrough/plan_cache_replan_group_lookup.js b/jstests/noPassthrough/plan_cache_replan_group_lookup.js
index 73d89c93b31..5da23cf502f 100644
--- a/jstests/noPassthrough/plan_cache_replan_group_lookup.js
+++ b/jstests/noPassthrough/plan_cache_replan_group_lookup.js
@@ -19,7 +19,6 @@ const coll = db.plan_cache_replan_group_lookup;
const foreignCollName = "foreign";
coll.drop();
-const sbePlanCacheEnabled = checkSBEEnabled(db, ["featureFlagSbePlanCache"]);
const sbeFullEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
function getPlansForCacheEntry(match) {
@@ -166,7 +165,7 @@ const aIndexPredicate = [{$match: {a: 1042, b: 1}}];
// {a: 1} index is used.
const bIndexPredicate = [{$match: {a: 1, b: 1042}}];
-const expectedVersion = sbePlanCacheEnabled ? 2 : 1;
+const expectedVersion = sbeFullEnabled ? 2 : 1;
// $group tests.
const groupSuffix = [{$group: {_id: "$c"}}, {$count: "n"}];
testFn(aIndexPredicate.concat(groupSuffix),
@@ -260,9 +259,9 @@ assert.eq(2, coll.aggregate(aLookup).toArray()[0].n);
// If SBE plan cache is enabled, a new cache entry will be created in the SBE plan cache after
// invalidation. The corresponding cache entry in SBE plan cache should be inactive because the SBE
// plan cache is invalidated on index drop.
-assertCacheUsage(sbePlanCacheEnabled /*multiPlanning*/,
+assertCacheUsage(sbeFullEnabled /*multiPlanning*/,
expectedVersion /* cacheEntryVersion */,
- !sbePlanCacheEnabled /*cacheEntryIsActive*/,
+ !sbeFullEnabled /*cacheEntryIsActive*/,
"a_1" /*cachedIndexName*/,
aLookup);
@@ -271,7 +270,7 @@ verifyCorrectLookupAlgorithmUsed("NestedLoopJoin", aLookup, {allowDiskUse: false
assert.eq(2, coll.aggregate(aLookup).toArray()[0].n);
// Note that multi-planning is expected here when the SBE plan cache is enabled because the
// 'allowDiskUse' value is part of the SBE plan cache key encoding.
-assertCacheUsage(sbePlanCacheEnabled /*multiPlanning*/,
+assertCacheUsage(sbeFullEnabled /*multiPlanning*/,
expectedVersion /* cacheEntryVersion */,
true /*cacheEntryIsActive*/,
"a_1" /*cachedIndexName*/,
@@ -281,9 +280,9 @@ assertCacheUsage(sbePlanCacheEnabled /*multiPlanning*/,
dropLookupForeignColl();
verifyCorrectLookupAlgorithmUsed("NonExistentForeignCollection", aLookup, {allowDiskUse: true});
assert.eq(2, coll.aggregate(aLookup).toArray()[0].n);
-assertCacheUsage(sbePlanCacheEnabled /*multiPlanning*/,
+assertCacheUsage(sbeFullEnabled /*multiPlanning*/,
expectedVersion /* cacheEntryVersion */,
- !sbePlanCacheEnabled /*cacheEntryIsActive*/,
+ !sbeFullEnabled /*cacheEntryIsActive*/,
"a_1" /*cachedIndexName*/,
aLookup);
@@ -346,10 +345,10 @@ verifyCorrectLookupAlgorithmUsed(
// If SBE plan cache is enabled, after dropping index, the $lookup plan cache will be invalidated.
// We will need to rerun the multi-planner.
-if (sbePlanCacheEnabled) {
+if (sbeFullEnabled) {
runLookupQuery({allowDiskUse: false});
assertCacheUsage(true /*multiPlanning*/,
- sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ 2 /* cacheEntryVersion */,
false /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline,
@@ -357,7 +356,7 @@ if (sbePlanCacheEnabled) {
runLookupQuery({allowDiskUse: false});
assertCacheUsage(true /*multiPlanning*/,
- sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ 2 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline,
@@ -366,7 +365,7 @@ if (sbePlanCacheEnabled) {
runLookupQuery({allowDiskUse: false});
assertCacheUsage(false /*multiPlanning*/,
- sbePlanCacheEnabled && sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline,
@@ -374,7 +373,7 @@ assertCacheUsage(false /*multiPlanning*/,
runLookupQuery({allowDiskUse: false});
assertCacheUsage(false /*multiPlanning*/,
- sbePlanCacheEnabled && sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline,
@@ -386,7 +385,7 @@ verifyCorrectLookupAlgorithmUsed("HashJoin", avoidReplanLookupPipeline, {allowDi
// If SBE plan cache is enabled, using different 'allowDiskUse' option will result in
// different plan cache key.
-if (sbePlanCacheEnabled) {
+if (sbeFullEnabled) {
runLookupQuery({allowDiskUse: true});
assertCacheUsage(true /*multiPlanning*/,
2 /* cacheEntryVersion */,
@@ -406,14 +405,14 @@ if (sbePlanCacheEnabled) {
runLookupQuery({allowDiskUse: true});
assertCacheUsage(false /*multiPlanning*/,
- sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline,
{allowDiskUse: true});
runLookupQuery({allowDiskUse: true});
assertCacheUsage(false /*multiPlanning*/,
- sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline,
@@ -439,25 +438,25 @@ verifyCorrectLookupAlgorithmUsed("IndexedLoopJoin", avoidReplanLookupPipeline);
// Set up an active cache entry.
runLookupQuery();
assertCacheUsage(true /*multiPlanning*/,
- sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
false /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline);
runLookupQuery();
assertCacheUsage(true /*multiPlanning*/,
- sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline);
runLookupQuery();
assertCacheUsage(false /*multiPlanning*/,
- sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline);
runLookupQuery();
assertCacheUsage(false /*multiPlanning*/,
- sbePlanCacheEnabled ? 2 : 1 /* cacheEntryVersion */,
+ sbeFullEnabled ? 2 : 1 /* cacheEntryVersion */,
true /*activeCacheEntry*/,
"b_1" /*cachedIndexName*/,
avoidReplanLookupPipeline);
@@ -472,7 +471,7 @@ let explain = coll.explain().aggregate(avoidReplanLookupPipeline);
const eqLookupNodes = getAggPlanStages(explain, "EQ_LOOKUP");
assert.eq(eqLookupNodes.length, 0, "expected no EQ_LOOKUP nodes; got " + tojson(explain));
-if (sbePlanCacheEnabled) {
+if (sbeFullEnabled) {
runLookupQuery();
const profileObj = getLatestProfilerEntry(db, {op: "command", ns: coll.getFullName()});
const matchingCacheEntries =
@@ -541,7 +540,7 @@ explain = coll.explain().aggregate(avoidReplanLookupPipeline);
groupNodes = getAggPlanStages(explain, "GROUP");
assert.eq(groupNodes.length, 0);
-if (sbePlanCacheEnabled) {
+if (sbeFullEnabled) {
runGroupQuery();
const profileObj = getLatestProfilerEntry(db, {op: "command", ns: coll.getFullName()});
const matchingCacheEntries =
diff --git a/jstests/noPassthrough/plan_cache_replan_sort.js b/jstests/noPassthrough/plan_cache_replan_sort.js
index e905c1a4425..711a2676a15 100644
--- a/jstests/noPassthrough/plan_cache_replan_sort.js
+++ b/jstests/noPassthrough/plan_cache_replan_sort.js
@@ -44,7 +44,7 @@ assert.eq(1, cachedPlans.length, cachedPlans);
assert.eq(true, cachedPlans[0].isActive, cachedPlans);
const cachedPlan = getCachedPlan(cachedPlans[0].cachedPlan);
const cachedPlanVersion = cachedPlans[0].version;
-if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
+if (checkSBEEnabled(db, ["featureFlagSbeFull"])) {
// If the SBE plan cache is on, then the cached plan has a different format.
assert.eq(cachedPlanVersion, "2", cachedPlans);
assert(cachedPlan.stages.includes("sort"), cachedPlans);
diff --git a/jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js b/jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js
index eecea2a2349..f5fe74022d1 100644
--- a/jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js
+++ b/jstests/noPassthrough/sbe_plan_cache_clear_on_param_change.js
@@ -48,10 +48,10 @@ assert.neq(conn, null, "mongod failed to start up");
const dbName = jsTestName();
const db = conn.getDB(dbName);
-// This test is specifically verifying the behavior of the SBE plan cache. So if either the SBE plan
-// cache or SBE itself are disabled, bail out.
-if (!checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
- jsTestLog("Skipping test because either SBE engine or SBE plan cache are disabled");
+// This test is specifically verifying the behavior of the SBE plan cache which is enabled by
+// 'featureFlagSbeFull'.
+if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+ jsTestLog("Skipping test because SBE is not fully enabled");
MongoRunner.stopMongod(conn);
return;
}
diff --git a/jstests/noPassthrough/sbe_plan_cache_key_reporting.js b/jstests/noPassthrough/sbe_plan_cache_key_reporting.js
index f6073656e67..7fbaee10118 100644
--- a/jstests/noPassthrough/sbe_plan_cache_key_reporting.js
+++ b/jstests/noPassthrough/sbe_plan_cache_key_reporting.js
@@ -20,8 +20,8 @@ assert.neq(conn, null, "mongod failed to start");
const db = conn.getDB("plan_cache_key_reporting");
const coll = db.coll;
-if (!checkSBEEnabled(db, ["featureFlagSbePlanCache"])) {
- jsTest.log("Skipping test because SBE plan cache is not enabled.");
+if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+ jsTest.log("Skipping test because SBE is not fully enabled");
MongoRunner.stopMongod(conn);
return;
}
diff --git a/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js b/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js
index 6a50b4db853..591c9c525d5 100644
--- a/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js
+++ b/jstests/noPassthrough/sbe_plan_cache_memory_debug_info.js
@@ -16,8 +16,8 @@ const conn = MongoRunner.runMongod({});
assert.neq(conn, null, "mongod failed to start");
const db = conn.getDB("sbe_plan_cache_memory_debug_info");
-if (!checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
- jsTest.log("Skipping test because SBE plan cache is not enabled.");
+if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+ jsTest.log("Skipping test because SBE is not fully enabled");
MongoRunner.stopMongod(conn);
return;
}
diff --git a/jstests/noPassthrough/sbe_plan_cache_size_metric.js b/jstests/noPassthrough/sbe_plan_cache_size_metric.js
index ebfe8d5f0bb..e41423704ed 100644
--- a/jstests/noPassthrough/sbe_plan_cache_size_metric.js
+++ b/jstests/noPassthrough/sbe_plan_cache_size_metric.js
@@ -21,6 +21,12 @@ const conn = MongoRunner.runMongod();
assert.neq(conn, null, "mongod failed to start");
const db = conn.getDB("sbe_plan_cache_size_metric");
+if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+ jsTest.log("Skipping test because SBE is not fully enabled");
+ MongoRunner.stopMongod(conn);
+ return;
+}
+
function getCacheEntriesByQueryHashKey(coll, queryHash) {
return coll.aggregate([{$planCacheStats: {}}, {$match: {queryHash}}]).toArray();
}
@@ -44,64 +50,64 @@ function assertQueryInPlanCache(coll, query) {
assert.eq(1, planCacheEntries.length, planCacheEntries);
}
-const isSbePlanCacheEnabled =
- checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]);
-if (isSbePlanCacheEnabled) {
- const collectionName = "plan_cache_sbe";
- const coll = db[collectionName];
- coll.drop();
-
- assert.commandWorked(coll.insert({a: 1, b: 1, c: 1}));
-
- // We need some indexes so that the multi-planner is executed.
- assert.commandWorked(coll.createIndex({a: 1}));
- assert.commandWorked(coll.createIndex({c: 1}));
- assert.commandWorked(coll.createIndex({a: 1, b: 1}));
-
- const initialPlanCacheSize = getPlanCacheSize();
- // Plan cache must be empty.
- assert.eq(0, coll.getPlanCache().list().length);
-
- const sbeQuery = {a: 1};
- const classicQuery = {a: 1, c: 1};
-
- // Step 1. Insert an entry to SBE Plan Cache.
- assert.eq(1, coll.find(sbeQuery).itcount());
- assertQueryInPlanCache(coll, sbeQuery);
- // Plan Cache must contain exactly 1 entry.
- assert.eq(1, coll.getPlanCache().list().length);
-
- // Assert metric is incremented for new cache entry.
- const afterSbePlanCacheSize = getPlanCacheSize();
- assert.gt(afterSbePlanCacheSize, initialPlanCacheSize);
-
- // Step 2. Insert an entry to Classic Plan Cache.
- // Force classic plan cache.
- assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true}));
- assert.eq(1, coll.find(classicQuery).itcount());
- assertQueryInPlanCache(coll, classicQuery);
- // Plan Cache must contain exactly 2 entries.
- assert.eq(2, coll.getPlanCache().list().length);
-
- // Assert metric is incremented for new cache entry.
- const afterClassicPlanCacheSize = getPlanCacheSize();
- assert.gt(afterClassicPlanCacheSize, afterSbePlanCacheSize);
-
- // Step 3. Remove the entry from Classic Plan Cache.
- // Clean up Classic Plan Cache.
- assert.commandWorked(db.runCommand({planCacheClear: collectionName, query: classicQuery}));
- // Assert metric is decremented back to values before insering classic plan cache entry.
- assert.eq(afterSbePlanCacheSize, getPlanCacheSize());
-
- // Step 4. Remove the entry from SBE Plan Cache.
- // Move back to SBE plan cache.
- assert.commandWorked(
- db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false}));
- // Clean up SBE Plan Cache
- assert.commandWorked(db.runCommand({planCacheClear: collectionName, query: sbeQuery}));
- // Assert metric is decremented back to initial value.
- assert.eq(initialPlanCacheSize, getPlanCacheSize());
-}
+const collectionName = "plan_cache_sbe";
+const coll = db[collectionName];
+coll.drop();
+
+assert.commandWorked(coll.insert({a: 1, b: 1, c: 1}));
+
+// We need some indexes so that the multi-planner is executed.
+assert.commandWorked(coll.createIndex({a: 1}));
+assert.commandWorked(coll.createIndex({c: 1}));
+assert.commandWorked(coll.createIndex({a: 1, b: 1}));
+
+const initialPlanCacheSize = getPlanCacheSize();
+// Plan cache must be empty.
+assert.eq(0, coll.getPlanCache().list().length);
+
+const sbeQuery = {
+ a: 1
+};
+const classicQuery = {
+ a: 1,
+ c: 1
+};
+
+// Step 1. Insert an entry to SBE Plan Cache.
+assert.eq(1, coll.find(sbeQuery).itcount());
+assertQueryInPlanCache(coll, sbeQuery);
+// Plan Cache must contain exactly 1 entry.
+assert.eq(1, coll.getPlanCache().list().length);
+
+// Assert metric is incremented for new cache entry.
+const afterSbePlanCacheSize = getPlanCacheSize();
+assert.gt(afterSbePlanCacheSize, initialPlanCacheSize);
+
+// Step 2. Insert an entry to Classic Plan Cache.
+// Force classic plan cache.
+assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: true}));
+assert.eq(1, coll.find(classicQuery).itcount());
+assertQueryInPlanCache(coll, classicQuery);
+// Plan Cache must contain exactly 2 entries.
+assert.eq(2, coll.getPlanCache().list().length);
+
+// Assert metric is incremented for new cache entry.
+const afterClassicPlanCacheSize = getPlanCacheSize();
+assert.gt(afterClassicPlanCacheSize, afterSbePlanCacheSize);
+
+// Step 3. Remove the entry from Classic Plan Cache.
+// Clean up Classic Plan Cache.
+assert.commandWorked(db.runCommand({planCacheClear: collectionName, query: classicQuery}));
+// Assert metric is decremented back to values before insering classic plan cache entry.
+assert.eq(afterSbePlanCacheSize, getPlanCacheSize());
+
+// Step 4. Remove the entry from SBE Plan Cache.
+// Move back to SBE plan cache.
+assert.commandWorked(db.adminCommand({setParameter: 1, internalQueryForceClassicEngine: false}));
+// Clean up SBE Plan Cache
+assert.commandWorked(db.runCommand({planCacheClear: collectionName, query: sbeQuery}));
+// Assert metric is decremented back to initial value.
+assert.eq(initialPlanCacheSize, getPlanCacheSize());
MongoRunner.stopMongod(conn);
})();
diff --git a/jstests/noPassthroughWithMongod/index_bounds_static_limit.js b/jstests/noPassthroughWithMongod/index_bounds_static_limit.js
index ea0af1d1537..dc183a27346 100644
--- a/jstests/noPassthroughWithMongod/index_bounds_static_limit.js
+++ b/jstests/noPassthroughWithMongod/index_bounds_static_limit.js
@@ -9,10 +9,8 @@
load("jstests/libs/analyze_plan.js"); // For explain helpers.
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-const isSBEEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
-
-if (!isSBEEnabled) {
- // This test is only relevant when SBE is enabled.
+if (!checkSBEEnabled(db, ["featureFlagSbeFull"])) {
+ jsTest.log("Skipping test because SBE is not fully enabled");
return;
}
@@ -54,21 +52,12 @@ function assertIndexScanPlan(explain, isGeneric) {
}
try {
- const isSBEPlanCacheEnabled = checkSBEEnabled(db, ["featureFlagSbePlanCache"]);
-
// Verify that when the number of statically generated single interval bounds is less than the
// static limit, the optimized plan is used.
const optimized =
coll.find({a: {$in: [1, 2, 3]}, b: {$in: [10, 11, 12]}, c: {$in: [42]}, d: {$lt: 3}})
.explain("executionStats");
-
- if (isSBEPlanCacheEnabled) {
- assertIndexScanPlan(optimized, /*isGeneric*/ false);
- } else {
- const optimiziedStages = optimized.executionStats.executionStages;
- assert(planHasStage(db, optimiziedStages, "ixseek"), optimiziedStages);
- assert(!planHasStage(db, optimiziedStages, "chkbounds"), optimiziedStages);
- }
+ assertIndexScanPlan(optimized, /*isGeneric*/ false);
// Verify that when the number of statically generated single interval bounds is greater than
// the static limit, the generic plan is used.
@@ -76,14 +65,7 @@ try {
const generic =
coll.find({a: {$in: [1, 2, 3]}, b: {$in: [10, 11, 12]}, c: {$in: [42]}, d: {$lt: 3}})
.explain("executionStats");
-
- if (isSBEPlanCacheEnabled) {
- assertIndexScanPlan(generic, /*isGeneric*/ true);
- } else {
- const genericStages = generic.executionStats.executionStages;
- assert(planHasStage(db, genericStages, "chkbounds"), genericStages);
- assert(planHasStage(db, genericStages, "ixseek"), genericStages);
- }
+ assertIndexScanPlan(generic, /*isGeneric*/ true);
} finally {
setStaticLimit(staticLimit);
}
diff --git a/jstests/noPassthroughWithMongod/ne_array_indexability.js b/jstests/noPassthroughWithMongod/ne_array_indexability.js
index 8c96060dbf6..f2ecb27151f 100644
--- a/jstests/noPassthroughWithMongod/ne_array_indexability.js
+++ b/jstests/noPassthroughWithMongod/ne_array_indexability.js
@@ -31,7 +31,7 @@ function runTest(queryToCache, queryToRunAfterCaching) {
// a different planCacheKey. The SBE plan cache, on the other hand, does not auto-parameterize
// $in or $eq involving a constant of type array, and therefore will consider the two queries to
// have different shapes.
- if (checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"])) {
+ if (checkSBEEnabled(db, ["featureFlagSbeFull"])) {
assert.neq(explain.queryPlanner.queryHash, cacheEntries[0].queryHash);
} else {
assert.eq(explain.queryPlanner.queryHash, cacheEntries[0].queryHash);
diff --git a/jstests/noPassthroughWithMongod/plan_cache_replanning.js b/jstests/noPassthroughWithMongod/plan_cache_replanning.js
index 5a45226ad1f..e17a81cb660 100644
--- a/jstests/noPassthroughWithMongod/plan_cache_replanning.js
+++ b/jstests/noPassthroughWithMongod/plan_cache_replanning.js
@@ -10,8 +10,7 @@ load('jstests/libs/analyze_plan.js'); // For getPlanStage().
load("jstests/libs/collection_drop_recreate.js"); // For assert[Drop|Create]Collection.
load("jstests/libs/sbe_util.js"); // For checkSBEEnabled.
-const isSbePlanCacheEnabled =
- checkSBEEnabled(db, ["featureFlagSbePlanCache", "featureFlagSbeFull"]);
+const isSbeEnabled = checkSBEEnabled(db, ["featureFlagSbeFull"]);
let coll = assertDropAndRecreateCollection(db, "plan_cache_replanning");
@@ -32,7 +31,7 @@ function assertPlanHasIxScanStage(entry, indexName, expectedQueryHash) {
assert.eq(entry.queryHash, expectedQueryHash, entry);
const cachedPlan = getCachedPlan(entry.cachedPlan);
- if (isSbePlanCacheEnabled) {
+ if (isSbeEnabled) {
// The $planCacheStats output for the SBE plan cache only contains an debug string
// representation of the execution plan. Rather than parse this string, we just check that
// the index name appears somewhere in the plan.
@@ -202,7 +201,7 @@ coll = assertDropAndRecreateCollection(db, "plan_cache_replanning");
// Execution stats from when the plan cache entry was created are not exposed from the SBE plan
// cache.
let specialValueCacheEntryKeysExamined;
- if (!isSbePlanCacheEnabled) {
+ if (!isSbeEnabled) {
specialValueCacheEntryKeysExamined = entry.creationExecStats[0].totalKeysExamined;
}
@@ -224,7 +223,7 @@ coll = assertDropAndRecreateCollection(db, "plan_cache_replanning");
// The new cache entry's plan should have used fewer works (and examined fewer keys) compared
// to the old cache entry's, since the query on the special value is slightly less efficient.
assert.lt(entry.works, specialValueCacheEntryWorks, entry);
- if (!isSbePlanCacheEnabled) {
+ if (!isSbeEnabled) {
assert.lt(entry.creationExecStats[0].totalKeysExamined,
specialValueCacheEntryKeysExamined,
entry);
@@ -240,7 +239,7 @@ coll = assertDropAndRecreateCollection(db, "plan_cache_replanning");
assertPlanHasIxScanStage(entry, "selectiveKey_1_tiebreak_1", queryHash);
assert.eq(entry.works, entryAfterRunningSpecialQuery.works, entryAfterRunningSpecialQuery);
- if (!isSbePlanCacheEnabled) {
+ if (!isSbeEnabled) {
assert.eq(entryAfterRunningSpecialQuery.creationExecStats[0].totalKeysExamined,
entry.creationExecStats[0].totalKeysExamined,
entryAfterRunningSpecialQuery);
diff --git a/src/mongo/db/commands/index_filter_commands.cpp b/src/mongo/db/commands/index_filter_commands.cpp
index 5deb5ecd339..699b8d99c69 100644
--- a/src/mongo/db/commands/index_filter_commands.cpp
+++ b/src/mongo/db/commands/index_filter_commands.cpp
@@ -232,7 +232,7 @@ Status ClearFilters::runIndexFilterCommand(OperationContext* opCtx,
sbe::PlanCache* planCacheSBE = nullptr;
invariant(planCacheClassic);
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
planCacheSBE = &sbe::getPlanCache(opCtx);
}
@@ -352,7 +352,7 @@ Status SetFilter::runIndexFilterCommand(OperationContext* opCtx,
sbe::PlanCache* planCacheSBE = nullptr;
invariant(planCacheClassic);
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
planCacheSBE = &sbe::getPlanCache(opCtx);
}
diff --git a/src/mongo/db/commands/plan_cache_clear_command.cpp b/src/mongo/db/commands/plan_cache_clear_command.cpp
index daf4bb18937..0b63f957d75 100644
--- a/src/mongo/db/commands/plan_cache_clear_command.cpp
+++ b/src/mongo/db/commands/plan_cache_clear_command.cpp
@@ -91,7 +91,7 @@ Status clear(OperationContext* opCtx,
// Default value of planner options (0) is SBE compatible, so it does not affect result of
// sbe::isQuerySbeCompatible here.
const size_t plannerOptions = 0;
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV() &&
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV() &&
!cq->getForceClassicEngine() &&
sbe::isQuerySbeCompatible(&collection, cq.get(), plannerOptions)) {
cq->setSbeCompatible(true);
@@ -112,7 +112,7 @@ Status clear(OperationContext* opCtx,
planCache->clear();
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
auto version = CollectionQueryInfo::get(collection).getPlanCacheInvalidatorVersion();
sbe::clearPlanCacheEntriesWith(opCtx->getServiceContext(), collection->uuid(), version);
}
diff --git a/src/mongo/db/exec/plan_cache_util.cpp b/src/mongo/db/exec/plan_cache_util.cpp
index 4f648536b64..1bd6f9fe75d 100644
--- a/src/mongo/db/exec/plan_cache_util.cpp
+++ b/src/mongo/db/exec/plan_cache_util.cpp
@@ -82,7 +82,7 @@ void updatePlanCache(OperationContext* opCtx,
// TODO SERVER-67576: re-enable caching of "explode for sort" plans in the SBE cache.
if (shouldCacheQuery(query) && collections.getMainCollection() &&
!solution.hasExplodedForSort &&
- feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
auto key = plan_cache_key_factory::make(query, collections);
auto plan = std::make_unique<sbe::CachedSbePlan>(root.clone(), data);
plan->indexFilterApplied = solution.indexFilterApplied;
diff --git a/src/mongo/db/exec/plan_cache_util.h b/src/mongo/db/exec/plan_cache_util.h
index 940fea8f575..b233338882f 100644
--- a/src/mongo/db/exec/plan_cache_util.h
+++ b/src/mongo/db/exec/plan_cache_util.h
@@ -200,7 +200,7 @@ void updatePlanCache(
if (winningPlan.solution->cacheData != nullptr) {
if constexpr (std::is_same_v<PlanStageType, std::unique_ptr<sbe::PlanStage>>) {
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
tassert(6142201,
"The winning CandidatePlan should contain the original plan",
winningPlan.clonedPlan);
@@ -224,8 +224,9 @@ void updatePlanCache(
&callbacks,
boost::none /* worksGrowthCoefficient */));
} else {
- // TODO SERVER-64882: Fall back to use the classic plan cache.
- // Remove this branch after "gFeatureFlagSbePlanCache" is removed.
+ // Fall back to use the classic plan cache.
+ //
+ // TODO SERVER-64882: Remove this branch after "gFeatureFlagSbeFull" is removed.
cacheClassicPlan();
}
} else {
diff --git a/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp b/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp
index 792cb69a079..4e13c886c71 100644
--- a/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp
+++ b/src/mongo/db/pipeline/process_interface/common_mongod_process_interface.cpp
@@ -554,7 +554,7 @@ std::vector<BSONObj> CommonMongodProcessInterface::getMatchingPlanCacheEntryStat
auto planCacheEntries =
planCache->getMatchingStats({} /* cacheKeyFilterFunc */, serializer, predicate);
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
// Retrieve plan cache entries from the SBE plan cache.
const auto cacheKeyFilter = [uuid = collection->uuid(),
collVersion = collQueryInfo.getPlanCacheInvalidatorVersion()](
diff --git a/src/mongo/db/query/canonical_query.cpp b/src/mongo/db/query/canonical_query.cpp
index 0df32aab8fa..674e44bfac9 100644
--- a/src/mongo/db/query/canonical_query.cpp
+++ b/src/mongo/db/query/canonical_query.cpp
@@ -202,7 +202,7 @@ Status CanonicalQuery::init(OperationContext* opCtx,
// If caching is disabled, do not perform any autoparameterization.
if (!internalQueryDisablePlanCache.load() &&
- feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
const bool hasNoTextNodes =
!QueryPlannerCommon::hasNode(_root.get(), MatchExpression::TEXT);
if (hasNoTextNodes) {
@@ -541,8 +541,8 @@ std::string CanonicalQuery::toStringShort() const {
}
CanonicalQuery::QueryShapeString CanonicalQuery::encodeKey() const {
- return (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV() &&
- !_forceClassicEngine && _sbeCompatible)
+ return (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV() && !_forceClassicEngine &&
+ _sbeCompatible)
? canonical_query_encoder::encodeSBE(*this)
: canonical_query_encoder::encode(*this);
}
diff --git a/src/mongo/db/query/canonical_query_encoder.cpp b/src/mongo/db/query/canonical_query_encoder.cpp
index c24be53a1b8..1ab4e5c89cf 100644
--- a/src/mongo/db/query/canonical_query_encoder.cpp
+++ b/src/mongo/db/query/canonical_query_encoder.cpp
@@ -1095,8 +1095,8 @@ void encodeKeyForAutoParameterizedMatchSBE(MatchExpression* matchExpr, BufBuilde
std::string encodeSBE(const CanonicalQuery& cq) {
tassert(6512900,
- "using the SBE plan cache key encoding requires the SBE plan cache to be enabled",
- feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV());
+ "using the SBE plan cache key encoding requires SBE to be fully enabled",
+ feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV());
tassert(6142104,
"attempting to encode SBE plan cache key for SBE-incompatible query",
cq.isSbeCompatible());
diff --git a/src/mongo/db/query/canonical_query_encoder_test.cpp b/src/mongo/db/query/canonical_query_encoder_test.cpp
index eb0719db9a5..359a50ab625 100644
--- a/src/mongo/db/query/canonical_query_encoder_test.cpp
+++ b/src/mongo/db/query/canonical_query_encoder_test.cpp
@@ -418,7 +418,7 @@ TEST(CanonicalQueryEncoderTest, ComputeKeySBE) {
// SBE must be enabled in order to generate SBE plan cache keys.
RAIIServerParameterControllerForTest controllerSBE("internalQueryForceClassicEngine", false);
- RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true);
+ RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbeFull", true);
testComputeSBEKey("{}", "{}", "{}", "YW4ABQAAAAAAAAAAAAAAAG5ubm4FAAAAAGZe");
testComputeSBEKey("{$or: [{a: 1}, {b: 2}]}",
@@ -536,7 +536,7 @@ TEST(CanonicalQueryEncoderTest, ComputeKeySBEWithPipeline) {
// SBE must be enabled in order to generate SBE plan cache keys.
RAIIServerParameterControllerForTest controllerSBE("internalQueryForceClassicEngine", false);
- RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true);
+ RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbeFull", true);
auto getLookupBson = [](StringData localField, StringData foreignField, StringData asField) {
return BSON("$lookup" << BSON("from" << foreignNss.coll() << "localField" << localField
@@ -596,7 +596,7 @@ TEST(CanonicalQueryEncoderTest, ComputeKeySBEWithPipeline) {
TEST(CanonicalQueryEncoderTest, ComputeKeySBEWithReadConcern) {
// SBE must be enabled in order to generate SBE plan cache keys.
RAIIServerParameterControllerForTest controllerSBE("internalQueryForceClassicEngine", false);
- RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true);
+ RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbeFull", true);
const auto sbeEncodingWithoutReadConcernAvailable =
"ZXEAYT8AAAAABQAAAAB+YWEAAAAAAAAAAG5ubm4FAAAAAGZe";
diff --git a/src/mongo/db/query/canonical_query_test.cpp b/src/mongo/db/query/canonical_query_test.cpp
index dbb2fd929da..a15a3b918b0 100644
--- a/src/mongo/db/query/canonical_query_test.cpp
+++ b/src/mongo/db/query/canonical_query_test.cpp
@@ -456,7 +456,7 @@ TEST(CanonicalQueryTest, InvalidSortOrdersFailToCanonicalize) {
}
TEST(CanonicalQueryTest, DoNotParameterizeTextExpressions) {
- RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true);
+ RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbeFull", true);
auto cq =
canonicalize("{$text: {$search: \"Hello World!\"}}",
MatchExpressionParser::kDefaultSpecialFeatures | MatchExpressionParser::kText);
@@ -464,7 +464,7 @@ TEST(CanonicalQueryTest, DoNotParameterizeTextExpressions) {
}
TEST(CanonicalQueryTest, DoParameterizeRegularExpressions) {
- RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbePlanCache", true);
+ RAIIServerParameterControllerForTest controllerSBEPlanCache("featureFlagSbeFull", true);
auto cq = canonicalize("{a: 1, b: {$lt: 5}}");
ASSERT_TRUE(cq->isParameterized());
}
diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp
index 8c7796209cb..cb6bc97957a 100644
--- a/src/mongo/db/query/explain.cpp
+++ b/src/mongo/db/query/explain.cpp
@@ -97,7 +97,7 @@ void generatePlannerInfo(PlanExecutor* exec,
const QuerySettings* querySettings =
QuerySettingsDecoration::get(mainCollection->getSharedDecorations());
if (exec->getCanonicalQuery()->isSbeCompatible() &&
- feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV() &&
+ feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV() &&
!exec->getCanonicalQuery()->getForceClassicEngine()) {
const auto planCacheKeyInfo =
plan_cache_key_factory::make(*exec->getCanonicalQuery(), collections);
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index d7dfc3ae66d..ae3c0d20c5f 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -1021,7 +1021,7 @@ protected:
// go through the normal planning and plan compilation process, resulting in an
// auto-parameterized SBE plan cache entry. Subsequent idhack queries can simply re-use this
// cache entry, and the hot path for recovering cached plans is already carefully optimized.
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
return nullptr;
}
@@ -1099,7 +1099,7 @@ protected:
std::unique_ptr<SlotBasedPrepareExecutionResult> buildCachedPlan(
const sbe::PlanCacheKey& planCacheKey) final {
if (shouldCacheQuery(*_cq)) {
- if (!feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (!feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
// If the feature flag is off, we first try to build an "id hack" plan because the
// id hack plans are not cached in the classic cache. We then fall back to use the
// classic plan cache.
@@ -1138,8 +1138,11 @@ protected:
return buildIdHackPlan();
}
- // A temporary function to allow recovering SBE plans from the classic plan cache.
- // TODO SERVER-61314: Remove this function when "featureFlagSbePlanCache" is removed.
+ // A temporary function to allow recovering SBE plans from the classic plan cache. When the
+ // feature flag for "SBE full" is disabled, we are still able to use the classic plan cache for
+ // queries that execute in SBE.
+ //
+ // TODO SERVER-64882: Remove this function when "featureFlagSbeFull" is removed.
std::unique_ptr<SlotBasedPrepareExecutionResult> buildCachedPlanFromClassicCache() {
const auto& mainColl = getMainCollection();
auto planCacheKey = plan_cache_key_factory::make<PlanCacheKey>(*_cq, mainColl);
diff --git a/src/mongo/db/query/query_feature_flags.idl b/src/mongo/db/query/query_feature_flags.idl
index df2bb74890b..e714b0f7e54 100644
--- a/src/mongo/db/query/query_feature_flags.idl
+++ b/src/mongo/db/query/query_feature_flags.idl
@@ -54,11 +54,6 @@ feature_flags:
default: true
version: 6.0
- featureFlagSbePlanCache:
- description: "Feature flag for enabling use of the SBE plan cache"
- cpp_varname: gFeatureFlagSbePlanCache
- default: false
-
featureFlagChangeStreamsFurtherEnrichedEvents:
description: "Feature flag for enabling the reshardCollection and refineCollectionShardKey events, as well as enhancements to the updateDescription field for update events"
cpp_varname: gFeatureFlagChangeStreamsFurtherEnrichedEvents
@@ -99,7 +94,8 @@ feature_flags:
default: false
featureFlagSbeFull:
- description: "Feature flag to enable using SBE for a larger number of queries"
+ description: "Feature flag for enabling full SBE support. Enables SBE for a much larger class
+ of queries, including NLJ $lookup plans. Also enables the SBE plan cache."
cpp_varname: gFeatureFlagSbeFull
default: false
diff --git a/src/mongo/db/query/sbe_cached_solution_planner.cpp b/src/mongo/db/query/sbe_cached_solution_planner.cpp
index d6b57f629ce..416610f401f 100644
--- a/src/mongo/db/query/sbe_cached_solution_planner.cpp
+++ b/src/mongo/db/query/sbe_cached_solution_planner.cpp
@@ -58,8 +58,11 @@ CandidatePlans CachedSolutionPlanner::plan(
// only track the number of reads from the local side. Thus, we can use the number of reads the
// plan was cached with during multiplanning even though multiplanning ran trials of
// pre-extended plans.
- if (!_cq.pipeline().empty() &&
- !feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ //
+ // When "featureFlagSbeFull" is enabled we use the SBE plan cache. The SBE plan cache stores the
+ // entire plan, including the part for any agg pipeline pushed down to SBE. Therefore, this
+ // logic is only necessary when "featureFlagSbeFull" is disabled.
+ if (!_cq.pipeline().empty() && !feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
_yieldPolicy->clearRegisteredPlans();
auto secondaryCollectionsInfo =
fillOutSecondaryCollectionsInformation(_opCtx, _collections, &_cq);
@@ -185,7 +188,7 @@ CandidatePlans CachedSolutionPlanner::replan(bool shouldCache, std::string reaso
// be simplified to only deactivate the entry in the SBE plan cache.
auto cache = CollectionQueryInfo::get(mainColl).getPlanCache();
cache->deactivate(plan_cache_key_factory::make<mongo::PlanCacheKey>(_cq, mainColl));
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
auto&& sbePlanCache = sbe::getPlanCache(_opCtx);
sbePlanCache.deactivate(plan_cache_key_factory::make(_cq, _collections));
}
diff --git a/src/mongo/db/query/sbe_plan_cache.cpp b/src/mongo/db/query/sbe_plan_cache.cpp
index bbd6db6418a..14d92b0d608 100644
--- a/src/mongo/db/query/sbe_plan_cache.cpp
+++ b/src/mongo/db/query/sbe_plan_cache.cpp
@@ -105,7 +105,7 @@ class PlanCacheOnParamChangeUpdaterImpl final : public plan_cache_util::OnParamC
public:
void updateCacheSize(ServiceContext* serviceCtx,
plan_cache_util::PlanCacheSizeParameter parameter) final {
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
auto size = getPlanCacheSizeInBytes(parameter);
auto& globalPlanCache = sbePlanCacheDecoration(serviceCtx);
globalPlanCache->reset(size);
@@ -113,7 +113,7 @@ public:
}
void clearCache(ServiceContext* serviceCtx) final {
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
auto& globalPlanCache = sbePlanCacheDecoration(serviceCtx);
globalPlanCache->clear();
}
@@ -125,7 +125,7 @@ ServiceContext::ConstructorActionRegisterer planCacheRegisterer{
plan_cache_util::sbePlanCacheOnParamChangeUpdater(serviceCtx) =
std::make_unique<PlanCacheOnParamChangeUpdaterImpl>();
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
auto status = plan_cache_util::PlanCacheSizeParameter::parse(planCacheSize.get());
uassertStatusOK(status);
@@ -139,15 +139,15 @@ ServiceContext::ConstructorActionRegisterer planCacheRegisterer{
sbe::PlanCache& getPlanCache(ServiceContext* serviceCtx) {
uassert(5933402,
- "Cannot getPlanCache() if gFeatureFlagSbePlanCache is disabled",
- feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV());
+ "Cannot getPlanCache() if 'featureFlagSbeFull' is disabled",
+ feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV());
return *sbePlanCacheDecoration(serviceCtx);
}
sbe::PlanCache& getPlanCache(OperationContext* opCtx) {
uassert(5933401,
- "Cannot getPlanCache() if gFeatureFlagSbePlanCache is disabled",
- feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV());
+ "Cannot getPlanCache() if 'featureFlagSbeFull' is disabled",
+ feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV());
tassert(5933400, "Cannot get the global SBE plan cache by a nullptr", opCtx);
return getPlanCache(opCtx->getServiceContext());
}
@@ -155,7 +155,7 @@ sbe::PlanCache& getPlanCache(OperationContext* opCtx) {
void clearPlanCacheEntriesWith(ServiceContext* serviceCtx,
UUID collectionUuid,
size_t collectionVersion) {
- if (feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ if (feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
auto removed =
sbe::getPlanCache(serviceCtx)
.removeIf([&collectionUuid, collectionVersion](const PlanCacheKey& key,
diff --git a/src/mongo/db/query/sbe_stage_builder_filter.cpp b/src/mongo/db/query/sbe_stage_builder_filter.cpp
index 50a58292484..adc537049e5 100644
--- a/src/mongo/db/query/sbe_stage_builder_filter.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_filter.cpp
@@ -2065,11 +2065,12 @@ std::pair<boost::optional<sbe::value::SlotId>, EvalStage> generateFilter(
return {boost::none, std::move(stage)};
}
- // We only use the classic matcher path (aka "franken matcher") when the plan cache is off,
- // because embedding the classic matcher into the query execution tree is not compatible with
- // auto parameterization. All of the constants used in the filter are in the MatchExpression
- // itself, rather than in slots.
- if (!feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ // We only use the classic matcher path (aka "franken matcher") when the SBE is not fully
+ // enabled. Fully enabling SBE turns on the SBE plan cache, and embedding the classic matcher
+ // into the query execution tree is not compatible with the plan cache's use of
+ // auto-parameterization. This is because when embedding the classic matcher all of the
+ // constants used in the filter are in the MatchExpression itself rather than in slots.
+ if (!feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
tassert(6681403, "trackIndex=true not supported for classic matcher in SBE", !trackIndex);
auto expr = makeFunction("applyClassicMatcher",
@@ -2106,11 +2107,12 @@ EvalStage generateIndexFilter(StageBuilderState& state,
return stage;
}
- // We only use the classic matcher path (aka "franken matcher") when the plan cache is off,
- // because embedding the classic matcher into the query execution tree is not compatible with
- // auto parameterization. All of the constants used in the filter are in the MatchExpression
- // itself, rather than in slots.
- if (!feature_flags::gFeatureFlagSbePlanCache.isEnabledAndIgnoreFCV()) {
+ // We only use the classic matcher path (aka "franken matcher") when SBE is not fully enabled.
+ // Fully enabling SBE turns on the SBE plan cache, and embedding the classic matcher into the
+ // query execution tree is not compatible with the plan cache's use of auto-parameterization.
+ // This is because when embedding the classic mathcer all of the constants used in the filter
+ // are in the MatchExpression itself rather than in slots.
+ if (!feature_flags::gFeatureFlagSbeFull.isEnabledAndIgnoreFCV()) {
BSONObjBuilder keyPatternBuilder;
for (auto& field : keyFields) {
keyPatternBuilder.append(field, 1);