SERVER-112851 Introduce knob to enerumate HashJoin plans from random join optimizer (#43217)

GitOrigin-RevId: 193bfb1114523de7f3dcca45c71f498338048857
This commit is contained in:
Ben Shteinfeld 2025-10-29 12:49:05 -04:00 committed by MongoDB Bot
parent 1957ab3e68
commit 788089a18d
7 changed files with 4256 additions and 53 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -38,22 +38,58 @@ assert.commandWorked(
);
function runBasicJoinTest(pipeline) {
subSection("No join opt");
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: false}));
outputAggregationPlanAndResults(coll, pipeline, {}, true, false);
try {
subSection("No join opt");
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: false}));
outputAggregationPlanAndResults(coll, pipeline, {}, true, false);
const noJoinOptResults = coll.aggregate(pipeline).toArray();
subSection("With random order, seed 44");
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: true}));
assert.commandWorked(db.adminCommand({setParameter: 1, internalRandomJoinOrderSeed: 44}));
outputAggregationPlanAndResults(coll, pipeline, {}, true, false);
subSection("With random order, seed 44, nested loop joins");
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: true}));
assert.commandWorked(db.adminCommand({setParameter: 1, internalRandomJoinOrderSeed: 44}));
outputAggregationPlanAndResults(coll, pipeline, {}, true, false);
const seed44NLJResults = coll.aggregate(pipeline).toArray();
subSection("With random order, seed 420");
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: true}));
assert.commandWorked(db.adminCommand({setParameter: 1, internalRandomJoinOrderSeed: 420}));
outputAggregationPlanAndResults(coll, pipeline, {}, true, false);
subSection("With random order, seed 44, hash join enabled");
assert.commandWorked(db.adminCommand({setParameter: 1, internalRandomJoinReorderDefaultToHashJoin: true}));
outputAggregationPlanAndResults(coll, pipeline, {}, true, false);
const seed44HJResults = coll.aggregate(pipeline).toArray();
// Reset flag.
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: false}));
assert.commandWorked(db.adminCommand({setParameter: 1, internalRandomJoinReorderDefaultToHashJoin: false}));
subSection("With random order, seed 420, nested loop joins");
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: true}));
assert.commandWorked(db.adminCommand({setParameter: 1, internalRandomJoinOrderSeed: 420}));
outputAggregationPlanAndResults(coll, pipeline, {}, true, false);
const seed420NLJResults = coll.aggregate(pipeline).toArray();
subSection("With random order, seed 420, hash join enabled");
assert.commandWorked(db.adminCommand({setParameter: 1, internalRandomJoinReorderDefaultToHashJoin: true}));
outputAggregationPlanAndResults(coll, pipeline, {}, true, false);
const seed420HJResults = coll.aggregate(pipeline).toArray();
// Validate that all execution modes return the same results.
assert(
_resultSetsEqualUnordered(noJoinOptResults, seed44NLJResults),
"Results differ between no join opt and seed 44 NLJ",
);
assert(
_resultSetsEqualUnordered(noJoinOptResults, seed44HJResults),
"Results differ between no join opt and seed 44 HJ",
);
assert(
_resultSetsEqualUnordered(noJoinOptResults, seed420NLJResults),
"Results differ between no join opt and seed 420 NLJ",
);
assert(
_resultSetsEqualUnordered(noJoinOptResults, seed420HJResults),
"Results differ between no join opt and seed 420 HJ",
);
} finally {
// Reset flags.
assert.commandWorked(db.adminCommand({setParameter: 1, internalEnableJoinOptimization: false}));
assert.commandWorked(db.adminCommand({setParameter: 1, internalRandomJoinReorderDefaultToHashJoin: false}));
}
}
section("Basic example with two joins");

View File

@ -243,6 +243,12 @@ std::unique_ptr<QuerySolution> constructSolutionWithRandomOrder(
ctx.makeJoinPreds(edge),
boost::none,
currentNode.embedPath);
} else if (internalRandomJoinReorderDefaultToHashJoin.load()) {
soln = std::make_unique<HashJoinEmbeddingNode>(std::move(soln),
std::move(rhs),
ctx.makeJoinPreds(edge),
boost::none,
currentNode.embedPath);
} else {
soln = std::make_unique<NestedLoopJoinEmbeddingNode>(std::move(soln),
std::move(rhs),

View File

@ -520,6 +520,15 @@ server_parameters:
on_update: plan_cache_util::clearSbeCacheOnParameterChange
redact: false
internalRandomJoinReorderDefaultToHashJoin:
description: "Change the default join algorithm produced from random reorderer from NestedLoopJoin to HashJoin."
set_at: [startup, runtime]
cpp_varname: "internalRandomJoinReorderDefaultToHashJoin"
cpp_vartype: AtomicWord<bool>
default: false
on_update: plan_cache_util::clearSbeCacheOnParameterChange
redact: false
internalQueryMaxPipelineRewrites:
description: "Maximum number of pipeline rewrite rules to apply"
set_at: [startup, runtime]