Files
mongo/jstests/sharding/query/group_plan_cache_sharded.js
Zac 591928c619 SERVER-108478 JS formatted by prettier and remove clang-format (#39656)
GitOrigin-RevId: 6c8f6aded47f260aa4f7c231b17dae3302cb1e04
2025-08-21 17:27:09 +00:00

90 lines
3.3 KiB
JavaScript

/**
* Test which verifies that the SBE plan cache correctly caches different plans for $group depending
* on whether the results will be fed into a merging pipeline or not.
*
* @tags: [
* requires_sharding,
* # This test as written assumes that we will get the same plan cache key for identical plans.
* # This assumption does not hold in multiversion scenarios, where the generated plan cache key
* # can change across versions.
* multiversion_incompatible,
* # This test uses the _id index
* expects_explicit_underscore_id_index,
* # This test is specifically verifying the behavior of the SBE plan cache, which is only enabled
* # when SBE is enabled.
* featureFlagSbeFull,
* ]
*/
import {ShardingTest} from "jstests/libs/shardingtest.js";
const st = new ShardingTest({shards: 2, rs: {nodes: 1}});
const mongosDB = st.s.getDB(jsTestName());
const collName = jsTestName();
const coll = mongosDB[collName];
function runPipeline(predicateValue) {
return coll
.aggregate([{$match: {_id: {$gte: predicateValue}}}, {$group: {_id: null, sumResult: {$sum: "$a"}}}])
.toArray();
}
// Shard coll on _id.
st.shardColl(coll, {_id: 1} /* key */, {_id: 0} /* split */, {_id: 0} /* move */, mongosDB.getName());
const docs = [
{_id: -2, a: 1},
{_id: 2, a: 2},
];
assert.commandWorked(coll.insertMany(docs));
assert.eq(0, coll.getPlanCache().list().length, "Expected 0 cache entries");
// Run the first aggregate, which will match the second document and target a single shard.
let res = runPipeline(0);
assert.eq(res.length, 1);
assert.eq(res[0], {_id: null, sumResult: 2}, res);
let cacheEntries = coll.getPlanCache().list();
assert.eq(1, cacheEntries.length, cacheEntries);
// Capture the plan cache key from our lone cache entry.
const nonMergingCacheEntry = cacheEntries[0];
assert(nonMergingCacheEntry.hasOwnProperty("planCacheKey"));
const nonMergingCacheKey = nonMergingCacheEntry.planCacheKey;
// Run the second aggregate, which will match both documents and target both shards.
res = runPipeline(-2000);
assert.eq(res.length, 1);
assert.eq(res[0], {_id: null, sumResult: 3}, res);
// The second aggregate will produce two additional cache entries; one for each shard.
cacheEntries = coll.getPlanCache().list();
assert.eq(3, cacheEntries.length, cacheEntries);
// Verify that all three cache entries are pinned and active. Then, verify that exactly one
// cache entry has the 'nonMergingCacheKey', while the other two have a different key.
let mergingCacheKey = null;
let mergingKeyCount = 0;
let nonMergingKeyCount = 0;
for (const cacheEntry of cacheEntries) {
assert(cacheEntry.isPinned, cacheEntry);
assert(cacheEntry.isActive, cacheEntry);
assert(cacheEntry.hasOwnProperty("planCacheKey"));
if (cacheEntry.planCacheKey === nonMergingCacheKey) {
nonMergingKeyCount++;
} else {
mergingKeyCount++;
// If we haven't seen the merging cache key before, stash it so that we can verify that the
// two merging plans have the exact same cache key.
if (mergingCacheKey === null) {
mergingCacheKey = cacheEntry.planCacheKey;
} else {
assert.eq(cacheEntry.planCacheKey, mergingCacheKey, tojson(cacheEntries));
}
}
}
assert.eq(nonMergingKeyCount, 1, tojson(cacheEntries));
assert.eq(mergingKeyCount, 2, tojson(cacheEntries));
st.stop();