compute: thin peek results by partitioning, not sorting - #38035
Closed
aljoscha wants to merge 1 commit into
Closed
Conversation
aljoscha
force-pushed
the
aljoscha/peek-01-cooperative
branch
from
August 4, 2026 08:56
a18f52c to
802ed32
Compare
aljoscha
force-pushed
the
aljoscha/peek-02-thinning
branch
from
August 4, 2026 08:56
c86c46b to
a8294a0
Compare
aljoscha
force-pushed
the
aljoscha/peek-01-cooperative
branch
from
August 4, 2026 09:00
802ed32 to
a0c373e
Compare
aljoscha
force-pushed
the
aljoscha/peek-02-thinning
branch
from
August 4, 2026 09:00
a8294a0 to
1da3c70
Compare
aljoscha
force-pushed
the
aljoscha/peek-01-cooperative
branch
from
August 4, 2026 09:22
a0c373e to
6bd2303
Compare
aljoscha
force-pushed
the
aljoscha/peek-02-thinning
branch
from
August 4, 2026 09:22
1da3c70 to
81b988e
Compare
aljoscha
force-pushed
the
aljoscha/peek-01-cooperative
branch
from
August 4, 2026 09:56
6bd2303 to
1b46946
Compare
aljoscha
force-pushed
the
aljoscha/peek-02-thinning
branch
from
August 4, 2026 09:56
81b988e to
7493416
Compare
aljoscha
force-pushed
the
aljoscha/peek-01-cooperative
branch
from
August 4, 2026 10:41
1b46946 to
ab66d73
Compare
aljoscha
force-pushed
the
aljoscha/peek-02-thinning
branch
from
August 4, 2026 10:41
7493416 to
db7baa0
Compare
aljoscha
marked this pull request as ready for review
August 4, 2026 10:56
When a peek's finishing bounds how many rows it can need, the scan keeps twice that many and periodically drops the excess. It did so by sorting the whole buffer and truncating, which costs a log factor per row for an order that is thrown away: the result is ordered once at the end, when the `RowCollection` is built. Partitioning gives the same retained rows in O(n) comparisons. Each comparison decodes both rows, so this is the dominant cost of a peek with an `ORDER BY` and a small `LIMIT` over a large arrangement. The partition is not stable, so when rows tie across the cut it is unspecified which survives. That is unobservable: a tie under this comparator means the rows are byte-identical, so whichever way the cut lands the retained run agrees with any other choice on its first `limit + offset` rows, and that prefix is all the finishing reads. `mz_index_peek_result_sort_seconds` becomes `mz_index_peek_result_thinning_seconds`, since it no longer times a sort. The one remaining sort, when the `RowCollection` is built, is timed by `mz_index_peek_row_collection_seconds`.
aljoscha
force-pushed
the
aljoscha/peek-01-cooperative
branch
from
August 4, 2026 11:41
ab66d73 to
40be927
Compare
aljoscha
force-pushed
the
aljoscha/peek-02-thinning
branch
from
August 4, 2026 11:41
db7baa0 to
6fc9408
Compare
Contributor
Author
|
Recreating on the correct base so GitHub picks up the stack. Superseded, see the replacement linked below. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Part 3 of 3 in a stack that makes index peeks stop monopolizing the compute
worker. Part 1 is #38039, part 2 is #38034.
When a peek's finishing bounds how many rows it can need, the scan keeps twice
that many and periodically drops the excess. It did so by sorting the whole
buffer and truncating. That costs a log factor per row for an order that is
thrown away: the result is ordered once at the end, when the
RowCollectionisbuilt. Each comparison decodes both rows, so for a peek with an
ORDER BYanda small
LIMITover a large arrangement this is the dominant cost.Part of CPU-195.
Description
select_nth_unstable_bygives the same retained rows in O(n) comparisonsinstead of O(n log k).
The partition is not stable, so when rows tie across the cut it is unspecified
which of them survives. That is unobservable, and the argument is worth stating
because it is the only thing making this a safe swap:
RowComparator::compare_rows(l, r, || l.cmp(r))means theorder_bycolumns compare equal and the tiebreaker compares equal, and thetiebreaker is a full comparison of the encoded rows. So tied rows are
byte-identical.
limit + offsetrows, whichever way the cut lands.RowSetFinishing::finishreads exactlyoffset..offset + limitof the mergedresult, and
merge_sorted's output prefix depends only on the runs' prefixes.So the client sees the same rows either way.
mz_index_peek_result_sort_secondsis renamed tomz_index_peek_result_thinning_seconds, since it no longer times a sort. Theone remaining sort, when the
RowCollectionis built, is timed bymz_index_peek_row_collection_seconds.Not changed on purpose. The unconditional sort in
RowCollection::new,which fires even when
order_byis empty, stays. It is load-bearing fordeterminism, not for correctness: per-worker peek responses are absorbed in
arrival order by a randomized
StreamMap, so sorting each run by encoded bytesplus a byte-order k-way merge in envd is what makes client-visible row order
reproducible independent of worker count and arrival order. Roughly 1100
multi-row, no-
ORDER BY,nosortsqllogictest goldens ride on it, andtest/sqllogictest/range.slt:359pins the length-first-then-bytes encodingorder exactly.
Verification
Covered by the existing suite: any change to which rows survive thinning, or to
their order, shows up in the sqllogictest goldens described above, since they
compare output positionally.