Repository navigation
fix: don't re-copy already emitted strings in Utf8View group-by emit - #27360
Kristofferjoha wants to merge 5 commits into
Conversation
|
run benchmarks |
|
Hi @Kristofferjoha, thanks for the request (#27360 (comment)). Only whitelisted users can trigger benchmarks. Allowed users: 2010YOUY01, Dandandan, Fokko, HippoBaro, Jefffrey, Omega359, Rachelint, Rich-T-kid, adriangb, alamb, asubiotto, avantgardnerio, brunal, buraksenn, cetra3, codephage2020, coderfender, comphead, erenavsarogullari, etseidl, friendlymatthew, gabotechs, geoffreyclaude, grtlr, haohuaijin, jayzhan211, jonathanc-n, kevinjqliu, klion26, kosiew, kumarUjjawal, kunalsinghdadhwal, liamzwbao, mbutrovich, mkleen, mzabaluev, neilconway, rluvaton, sdf-jkl, timsaucer, xudong963, zhuqi-lucas. File an issue against this benchmark runner |
vinycalves
left a comment
There was a problem hiding this comment.
Two logic questions; no code suggestions.
There was a problem hiding this comment.
The offset shift is subtracted from every non-inlined view. Does that rely on all remaining views pointing to the in-progress buffer, and is the mixed completed/in-progress case tested? Also, is drain O(n^2) when many groups remain across repeated partial emits?
There was a problem hiding this comment.
Added the test. As for the drain, it shouldnt really matter, as it is capped at a specific block size. Should stay linear. But i want the benchmark ran to make sure
|
Cna you pleaes provide an end to end test / reproducer of what you are trying to do (rather than code level description / unit test)? |
|
@Kristofferjoha the issue report includes a minimal reproducible example you should be able to work into an SLT test |
| query I | ||
| COPY ( | ||
| SELECT value % 1000 AS k, repeat('x', 100) || (value % 7)::varchar AS s, value AS v | ||
| FROM generate_series(1, 2000000) | ||
| ORDER BY k | ||
| ) |
There was a problem hiding this comment.
How long does this test take to run? Can we reduce the data sizes and still reproduce?
Which issue does this PR close?
Rationale for this change
A streaming GROUP BY with a Utf8View column among several group columns emits small batches that carry far more string data than their rows use. The cause is in
ByteViewGroupValueBuilder::take_n. On each partial emit it copies the in-progress string buffer from byte 0 up to the last emitted string, and never trims that buffer. So every emitted batch carries the strings of all earlier batches from the same block.What changes are included in this PR?
After a partial take from the in-progress buffer, drain the taken bytes from it and shift the offsets of the remaining views. Each emitted batch then holds only its own strings.
drainmoves the not-yet-emitted bytes to the front of the buffer on each partial emit. In the streaming case that is only a few groups.Not changed: when the last emitted string is in a completed block, the emitted batch still shares that whole block (up to 2 MB). In the streaming case that should now be rare, since the in-progress buffer only holds groups not yet emitted.
What is the testing strategy for this PR?
New unit test
test_byte_view_take_n_drains_in_progress. It takes one row at a time and checks that each emitted array's data buffer holds only its own string, that the in-progress buffer shrinks, and that the remaining and newly appended values are still correct.I also ran the repro from the issue with the cli, and compared to main:
main-m 200M-m 50M-m 20M-m 10MEXPLAIN ANALYZEof the same query without a memory limit:mainoutput_bytesAggregateExec(Partial)RepartitionExecAre there any user-facing changes?
No