Skip to content

REP-6492 Switch to $sampleRate-style partitioning #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Aug 21, 2025

Conversation

FGasper
Copy link
Collaborator

@FGasper FGasper commented Aug 18, 2025

$sample-based partitioning has proven problematic for some years now because it often creates highly-imbalanced partitions.

This changeset switches partitioning to use $sampleRate instead. Because this entails a full index scan it tends to be slower; we offset that by creating partition tasks immediately as we receive sampled partition boundaries rather than all at once at the end of the aggregation.

Because MongoDB 4.2 lacked $sampleRate (and $rand as well), the legacy partitioning logic remains for use with that server version.

Both legacy & $sampleRate partitioning are made to use available read concern and secondaryPreferred read preference. These aggregations don’t need consistency, but they benefit substantially from speed & minimizing workload on the primary.

A few simplifications are made here as well. For example, MongosyncID is removed from the PartitionKey struct since it’s never actually relevant, and certain parameters to the legacy partitioner are made constant (since they were always used thus). The util.Divide function is renamed util.DivideToF64 to clarify that its return is a float.

@FGasper FGasper force-pushed the REP-6492-samplerate-partition branch from 180b79a to ab5b493 Compare August 20, 2025 17:13
@FGasper FGasper requested a review from tdq45gj August 20, 2025 19:40
@FGasper FGasper marked this pull request as ready for review August 20, 2025 19:40
Copy link
Collaborator

@tdq45gj tdq45gj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good in general. I left some comments on small points.

@FGasper FGasper requested a review from tdq45gj August 21, 2025 19:00
Comment on lines 92 to 103
/*
_, err := verifier.verificationTaskCollection().InsertOne(
ctx,
task,
)
require.NoError(err, "should insert collection task")

require.NoError(
verifier.ProcessCollectionVerificationTask(ctx, 0, task),
"task should succeed",
)
*/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this in the test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, removed

@@ -95,8 +95,9 @@ func (verifier *Verifier) createPartitionTasksWithSampleRateRetryable(
}

pipeline := mongo.Pipeline{
{{"$project", bson.D{{"_id", 1}}}},
// NB: $sort MUST precede $project in order to avoid a blocking sort.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be more specific that it's only a problem for versions before v6.0.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines 200 to 201
idealNumPartitions := util.Divide(collBytes, idealPartitionBytes)
docsPerPartition := util.Divide(docsCount, idealNumPartitions)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that it's still possible to get division by 0 error. If collBytes < idealPartitionBytes, idealNumPartitions would become 0. Could we limit idealNumPartitions and docsPerPartition to be larger than 1?

Suggested change
idealNumPartitions := util.Divide(collBytes, idealPartitionBytes)
docsPerPartition := util.Divide(docsCount, idealNumPartitions)
idealNumPartitions := min(1, util.Divide(collBytes, idealPartitionBytes))
docsPerPartition := min(1, util.Divide(docsCount, idealNumPartitions))

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

util.Divide() returns a float, so that shouldn’t happen, but I’ve tweaked the logic anyhow.

@FGasper FGasper requested a review from tdq45gj August 21, 2025 19:45
Copy link
Collaborator

@tdq45gj tdq45gj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@FGasper FGasper merged commit f398a89 into mongodb-labs:main Aug 21, 2025
98 checks passed
@FGasper FGasper deleted the REP-6492-samplerate-partition branch August 21, 2025 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants