summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp')
-rw-r--r--src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp203
1 files changed, 65 insertions, 138 deletions
diff --git a/src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp b/src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp
index 89244fd4589..87fc8dbd1f2 100644
--- a/src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp
+++ b/src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp
@@ -69,23 +69,18 @@ void HashAggStageTest::performHashAggWithSpillChecking(
auto makeStageFn = [this, collatorSlot, shouldUseCollator, shouldSpill](
value::SlotId scanSlot, std::unique_ptr<PlanStage> scanStage) {
auto countsSlot = generateSlotId();
- auto spillSlot = generateSlotId();
auto hashAggStage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(scanSlot),
- makeSlotExprPairVec(
- countsSlot,
- stage_builder::makeFunction("sum",
- makeE<EConstant>(value::TypeTags::NumberInt64,
- value::bitcastFrom<int64_t>(1)))),
+ makeEM(countsSlot,
+ stage_builder::makeFunction("sum",
+ makeE<EConstant>(value::TypeTags::NumberInt64,
+ value::bitcastFrom<int64_t>(1)))),
makeSV(),
true,
boost::optional<value::SlotId>{shouldUseCollator, collatorSlot},
shouldSpill,
- makeSlotExprPairVec(
- spillSlot,
- stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot))),
kEmptyPlanNodeId);
return std::make_pair(countsSlot, std::move(hashAggStage));
@@ -171,21 +166,20 @@ TEST_F(HashAggStageTest, HashAggMinMaxTest) {
auto hashAggStage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(),
- makeSlotExprPairVec(minSlot,
- stage_builder::makeFunction("min", makeE<EVariable>(scanSlot)),
- maxSlot,
- stage_builder::makeFunction("max", makeE<EVariable>(scanSlot)),
- collMinSlot,
- stage_builder::makeFunction(
- "collMin", collExpr->clone(), makeE<EVariable>(scanSlot)),
- collMaxSlot,
- stage_builder::makeFunction(
- "collMax", collExpr->clone(), makeE<EVariable>(scanSlot))),
+ makeEM(minSlot,
+ stage_builder::makeFunction("min", makeE<EVariable>(scanSlot)),
+ maxSlot,
+ stage_builder::makeFunction("max", makeE<EVariable>(scanSlot)),
+ collMinSlot,
+ stage_builder::makeFunction(
+ "collMin", collExpr->clone(), makeE<EVariable>(scanSlot)),
+ collMaxSlot,
+ stage_builder::makeFunction(
+ "collMax", collExpr->clone(), makeE<EVariable>(scanSlot))),
makeSV(),
true,
boost::none,
false /* allowDiskUse */,
- makeSlotExprPairVec() /* mergingExprs */,
kEmptyPlanNodeId);
auto outSlot = generateSlotId();
@@ -236,15 +230,13 @@ TEST_F(HashAggStageTest, HashAggAddToSetTest) {
auto hashAggStage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(),
- makeSlotExprPairVec(hashAggSlot,
- stage_builder::makeFunction("collAddToSet",
- std::move(collExpr),
- makeE<EVariable>(scanSlot))),
+ makeEM(hashAggSlot,
+ stage_builder::makeFunction(
+ "collAddToSet", std::move(collExpr), makeE<EVariable>(scanSlot))),
makeSV(),
true,
boost::none,
false /* allowDiskUse */,
- makeSlotExprPairVec() /* mergingExprs */,
kEmptyPlanNodeId);
return std::make_pair(hashAggSlot, std::move(hashAggStage));
@@ -335,16 +327,14 @@ TEST_F(HashAggStageTest, HashAggSeekKeysTest) {
auto hashAggStage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(scanSlot),
- makeSlotExprPairVec(
- countsSlot,
- stage_builder::makeFunction("sum",
- makeE<EConstant>(value::TypeTags::NumberInt64,
- value::bitcastFrom<int64_t>(1)))),
+ makeEM(countsSlot,
+ stage_builder::makeFunction("sum",
+ makeE<EConstant>(value::TypeTags::NumberInt64,
+ value::bitcastFrom<int64_t>(1)))),
makeSV(seekSlot),
true,
boost::none,
false /* allowDiskUse */,
- makeSlotExprPairVec() /* mergingExprs */,
kEmptyPlanNodeId);
return std::make_pair(countsSlot, std::move(hashAggStage));
@@ -397,21 +387,17 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpill) {
// Build a HashAggStage, group by the scanSlot and compute a simple count.
auto countsSlot = generateSlotId();
- auto spillSlot = generateSlotId();
auto stage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(scanSlot),
- makeSlotExprPairVec(
- countsSlot,
- stage_builder::makeFunction(
- "sum",
- makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
+ makeEM(countsSlot,
+ stage_builder::makeFunction(
+ "sum",
+ makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
makeSV(), // Seek slot
true,
boost::none,
true /* allowDiskUse */,
- makeSlotExprPairVec(
- spillSlot, stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot))),
kEmptyPlanNodeId);
// Prepare the tree and get the 'SlotAccessor' for the output slot.
@@ -434,7 +420,6 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpill) {
// Check that the spilling behavior matches the expected.
auto stats = static_cast<const HashAggStats*>(stage->getSpecificStats());
ASSERT_FALSE(stats->usedDisk);
- ASSERT_EQ(0, stats->numSpills);
ASSERT_EQ(0, stats->spilledRecords);
stage->close();
@@ -443,6 +428,7 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpill) {
TEST_F(HashAggStageTest, HashAggBasicCountSpill) {
// We estimate the size of result row like {int64, int64} at 50B. Set the memory threshold to
// 64B so that exactly one row fits in memory.
+ const int expectedRowsToFitInMemory = 1;
auto defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill =
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(64);
@@ -460,21 +446,17 @@ TEST_F(HashAggStageTest, HashAggBasicCountSpill) {
// Build a HashAggStage, group by the scanSlot and compute a simple count.
auto countsSlot = generateSlotId();
- auto spillSlot = generateSlotId();
auto stage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(scanSlot),
- makeSlotExprPairVec(
- countsSlot,
- stage_builder::makeFunction(
- "sum",
- makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
+ makeEM(countsSlot,
+ stage_builder::makeFunction(
+ "sum",
+ makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
makeSV(), // Seek slot
true,
boost::none,
true /* allowDiskUse */,
- makeSlotExprPairVec(
- spillSlot, stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot))),
kEmptyPlanNodeId);
// Prepare the tree and get the 'SlotAccessor' for the output slot.
@@ -497,14 +479,7 @@ TEST_F(HashAggStageTest, HashAggBasicCountSpill) {
// Check that the spilling behavior matches the expected.
auto stats = static_cast<const HashAggStats*>(stage->getSpecificStats());
ASSERT_TRUE(stats->usedDisk);
- // Memory usage is estimated only every two rows at the most frequent. Also, we only start
- // spilling after estimating that the memory budget is exceeded. These two factors result in
- // fewer expected spills than there are input records, even though only one record fits in
- // memory at a time.
- ASSERT_EQ(stats->numSpills, 3);
- // The input has one run of two consecutive values, so we expect to spill as many records as
- // there are input values minus one.
- ASSERT_EQ(stats->spilledRecords, 8);
+ ASSERT_EQ(results.size() - expectedRowsToFitInMemory, stats->spilledRecords);
stage->close();
}
@@ -538,21 +513,17 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpillIfNoMemCheck) {
// Build a HashAggStage, group by the scanSlot and compute a simple count.
auto countsSlot = generateSlotId();
- auto spillSlot = generateSlotId();
auto stage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(scanSlot),
- makeSlotExprPairVec(
- countsSlot,
- stage_builder::makeFunction(
- "sum",
- makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
+ makeEM(countsSlot,
+ stage_builder::makeFunction(
+ "sum",
+ makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
makeSV(), // Seek slot
true,
boost::none,
true /* allowDiskUse */,
- makeSlotExprPairVec(
- spillSlot, stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot))),
kEmptyPlanNodeId);
// Prepare the tree and get the 'SlotAccessor' for the output slot.
@@ -575,7 +546,6 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpillIfNoMemCheck) {
// Check that it did not spill.
auto stats = static_cast<const HashAggStats*>(stage->getSpecificStats());
ASSERT_FALSE(stats->usedDisk);
- ASSERT_EQ(0, stats->numSpills);
ASSERT_EQ(0, stats->spilledRecords);
stage->close();
@@ -584,6 +554,7 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpillIfNoMemCheck) {
TEST_F(HashAggStageTest, HashAggBasicCountSpillDouble) {
// We estimate the size of result row like {double, int64} at 50B. Set the memory threshold to
// 64B so that exactly one row fits in memory.
+ const int expectedRowsToFitInMemory = 1;
auto defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill =
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(64);
@@ -601,21 +572,17 @@ TEST_F(HashAggStageTest, HashAggBasicCountSpillDouble) {
// Build a HashAggStage, group by the scanSlot and compute a simple count.
auto countsSlot = generateSlotId();
- auto spillSlot = generateSlotId();
auto stage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(scanSlot),
- makeSlotExprPairVec(
- countsSlot,
- stage_builder::makeFunction(
- "sum",
- makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
+ makeEM(countsSlot,
+ stage_builder::makeFunction(
+ "sum",
+ makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
makeSV(), // Seek slot
true,
boost::none,
true /* allowDiskUse */,
- makeSlotExprPairVec(
- spillSlot, stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot))),
kEmptyPlanNodeId);
// Prepare the tree and get the 'SlotAccessor' for the output slot.
@@ -638,14 +605,7 @@ TEST_F(HashAggStageTest, HashAggBasicCountSpillDouble) {
// Check that the spilling behavior matches the expected.
auto stats = static_cast<const HashAggStats*>(stage->getSpecificStats());
ASSERT_TRUE(stats->usedDisk);
- // Memory usage is estimated only every two rows at the most frequent. Also, we only start
- // spilling after estimating that the memory budget is exceeded. These two factors result in
- // fewer expected spills than there are input records, even though only one record fits in
- // memory at a time.
- ASSERT_EQ(stats->numSpills, 3);
- // The input has one run of two consecutive values, so we expect to spill as many records as
- // there are input values minus one.
- ASSERT_EQ(stats->spilledRecords, 8);
+ ASSERT_EQ(results.size() - expectedRowsToFitInMemory, stats->spilledRecords);
stage->close();
}
@@ -667,21 +627,17 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpillWithNoGroupByDouble) {
// Build a HashAggStage, with an empty group by slot and compute a simple count.
auto countsSlot = generateSlotId();
- auto spillSlot = generateSlotId();
auto stage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(),
- makeSlotExprPairVec(
- countsSlot,
- stage_builder::makeFunction(
- "sum",
- makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
+ makeEM(countsSlot,
+ stage_builder::makeFunction(
+ "sum",
+ makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
makeSV(), // Seek slot
true,
boost::none,
true /* allowDiskUse */,
- makeSlotExprPairVec(
- spillSlot, stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot))),
kEmptyPlanNodeId);
// Prepare the tree and get the 'SlotAccessor' for the output slot.
@@ -702,7 +658,6 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpillWithNoGroupByDouble) {
// Check that the spilling behavior matches the expected.
auto stats = static_cast<const HashAggStats*>(stage->getSpecificStats());
ASSERT_FALSE(stats->usedDisk);
- ASSERT_EQ(0, stats->numSpills);
ASSERT_EQ(0, stats->spilledRecords);
stage->close();
@@ -711,6 +666,7 @@ TEST_F(HashAggStageTest, HashAggBasicCountNoSpillWithNoGroupByDouble) {
TEST_F(HashAggStageTest, HashAggMultipleAccSpill) {
// We estimate the size of result row like {double, int64} at 59B. Set the memory threshold to
// 128B so that two rows fit in memory.
+ const int expectedRowsToFitInMemory = 2;
auto defaultInternalQuerySBEAggApproxMemoryUseInBytesBeforeSpill =
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.load();
internalQuerySBEAggApproxMemoryUseInBytesBeforeSpill.store(128);
@@ -729,27 +685,19 @@ TEST_F(HashAggStageTest, HashAggMultipleAccSpill) {
// Build a HashAggStage, group by the scanSlot and compute a simple count.
auto countsSlot = generateSlotId();
auto sumsSlot = generateSlotId();
- auto spillSlot1 = generateSlotId();
- auto spillSlot2 = generateSlotId();
auto stage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(scanSlot),
- makeSlotExprPairVec(
- countsSlot,
- stage_builder::makeFunction(
- "sum",
- makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1))),
- sumsSlot,
- stage_builder::makeFunction("sum", makeE<EVariable>(scanSlot))),
+ makeEM(countsSlot,
+ stage_builder::makeFunction(
+ "sum",
+ makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1))),
+ sumsSlot,
+ stage_builder::makeFunction("sum", makeE<EVariable>(scanSlot))),
makeSV(), // Seek slot
true,
boost::none,
true /* allowDiskUse */,
- makeSlotExprPairVec(
- spillSlot1,
- stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot1)),
- spillSlot2,
- stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot2))),
kEmptyPlanNodeId);
// Prepare the tree and get the 'SlotAccessor' for the output slot.
@@ -779,10 +727,7 @@ TEST_F(HashAggStageTest, HashAggMultipleAccSpill) {
// Check that the spilling behavior matches the expected.
auto stats = static_cast<const HashAggStats*>(stage->getSpecificStats());
ASSERT_TRUE(stats->usedDisk);
- ASSERT_EQ(stats->numSpills, 3);
- // The input has one run of two consecutive values, so we expect to spill as many records as
- // there are input values minus one.
- ASSERT_EQ(stats->spilledRecords, 8);
+ ASSERT_EQ(results.size() - expectedRowsToFitInMemory, stats->spilledRecords);
stage->close();
}
@@ -807,27 +752,19 @@ TEST_F(HashAggStageTest, HashAggMultipleAccSpillAllToDisk) {
// Build a HashAggStage, group by the scanSlot and compute a simple count.
auto countsSlot = generateSlotId();
auto sumsSlot = generateSlotId();
- auto spillSlot1 = generateSlotId();
- auto spillSlot2 = generateSlotId();
auto stage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(scanSlot),
- makeSlotExprPairVec(
- countsSlot,
- stage_builder::makeFunction(
- "sum",
- makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1))),
- sumsSlot,
- stage_builder::makeFunction("sum", makeE<EVariable>(scanSlot))),
+ makeEM(countsSlot,
+ stage_builder::makeFunction(
+ "sum",
+ makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1))),
+ sumsSlot,
+ stage_builder::makeFunction("sum", makeE<EVariable>(scanSlot))),
makeSV(), // Seek slot
true,
boost::none,
true, // allowDiskUse=true
- makeSlotExprPairVec(
- spillSlot1,
- stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot1)),
- spillSlot2,
- stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot2))),
kEmptyPlanNodeId);
// Prepare the tree and get the 'SlotAccessor' for the output slot.
@@ -857,9 +794,7 @@ TEST_F(HashAggStageTest, HashAggMultipleAccSpillAllToDisk) {
// Check that the spilling behavior matches the expected.
auto stats = static_cast<const HashAggStats*>(stage->getSpecificStats());
ASSERT_TRUE(stats->usedDisk);
- // We expect each incoming value to result in a spill of a single record.
- ASSERT_EQ(stats->numSpills, 9);
- ASSERT_EQ(stats->spilledRecords, 9);
+ ASSERT_EQ(results.size(), stats->spilledRecords);
stage->close();
}
@@ -896,18 +831,14 @@ TEST_F(HashAggStageTest, HashAggSum10Groups) {
// Build a HashAggStage, group by the scanSlot and compute a sum for each group.
auto sumsSlot = generateSlotId();
- auto spillSlot = generateSlotId();
auto stage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(scanSlot),
- makeSlotExprPairVec(sumsSlot,
- stage_builder::makeFunction("sum", makeE<EVariable>(scanSlot))),
+ makeEM(sumsSlot, stage_builder::makeFunction("sum", makeE<EVariable>(scanSlot))),
makeSV(), // Seek slot
true,
boost::none,
true, // allowDiskUse=true
- makeSlotExprPairVec(
- spillSlot, stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot))),
kEmptyPlanNodeId);
// Prepare the tree and get the 'SlotAccessor' for the output slot.
@@ -941,21 +872,17 @@ TEST_F(HashAggStageTest, HashAggBasicCountWithRecordIds) {
// Build a HashAggStage, group by the scanSlot and compute a simple count.
auto countsSlot = generateSlotId();
- auto spillSlot = generateSlotId();
auto stage = makeS<HashAggStage>(
std::move(scanStage),
makeSV(scanSlot),
- makeSlotExprPairVec(
- countsSlot,
- stage_builder::makeFunction(
- "sum",
- makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
+ makeEM(countsSlot,
+ stage_builder::makeFunction(
+ "sum",
+ makeE<EConstant>(value::TypeTags::NumberInt64, value::bitcastFrom<int64_t>(1)))),
makeSV(), // Seek slot
true,
boost::none,
true, // allowDiskUse=true
- makeSlotExprPairVec(
- spillSlot, stage_builder::makeFunction("sum", stage_builder::makeVariable(spillSlot))),
kEmptyPlanNodeId);
// Prepare the tree and get the 'SlotAccessor' for the output slot.