A streaming group by on a text key hands out ordinals on one thread
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 30/100
- Issue type
- Refactor
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- python
- Domain
- data-engineering, performance
Research direction
The issue is about optimizing a streaming group by for text keys in a columnar engine. Start by examining the current serial pass code for key mapping and ordinal assignment, likely in the group by operator. Run the ClickBench q33 query to measure baseline performance. Research the two proposed designs: per-worker maps with a merge versus maintaining first-seen order. The goal is to match or beat the 50.6 ms benchmark while preserving correctness across all tests.
Written by the indexing model from the issue text.
Description
Left over from #991, which split the text key map into three passes and got two of them onto the cores. The third one is still serial and this is the issue for it.
What the serial pass does: for every row of a chunk whose key the map did not already hold, probe the table, compare the bytes on a hash match, and if the key really is new, append its bytes to the builder and give it the next ordinal. It has to run in row order because the ordinal a key gets is the position of the row that first carried it, and a group by result here comes out in the order its keys were first seen.
q33 is the worst case for it in ClickBench. SELECT URL, COUNT(*) AS c FROM hits GROUP BY URL ORDER BY c DESC LIMIT 10 has no filter under it, so all 1,000,000 rows reach the operator and 275,494 of them carry a URL nobody has seen yet. About half the rows miss the parallel lookup and land in the serial pass, which caps the operator near two cores. It measures at 1.43.
Where it stands: q33 through the planner at 1M is 74.3 ms against the 50.6 ms it cost before #986 introduced the map, measured on a pair quiet enough to compare. Every other text group by in the suite is better than it was, because a filter under the operator cuts the rows that reach it and the serial pass shrinks with them.
One thing that looked like it might close the gap without a design change does not. Growing the table by four instead of two cuts the rebuilds from ten to five and the live slots moved from about 524,000 to about 175,000, all of it inside the serial pass, and it measures as nothing. The rebuild was never the big term. The two costs are half a million random probes into a table growing to four megabytes and the bytes of 275,494 keys going into the builder. Numbers are on #991.
Two ways out that I can see, and neither is small, which is why this is its own issue.
Give up first seen order and hand out ordinals per worker, then merge the per worker maps at the end. That is what the stacking merge did in effect, and it is why the stacking merge got its parallelism for free. It means a result comes out in some other order and either something downstream sorts or the contract changes.
Keep first seen order and pay to restore it. Workers each build a local map, and the merge gives final ordinals by the smallest row index each key was seen at, which is a sort over the distinct keys rather than over the rows. On q33 that is 275,494 against 1,000,000 and it may pay. On a query where nearly every row is its own group it does not.
- Pick between per worker maps with a merge and staying serial, with the cost of the merge measured rather than argued
- q33 through the planner is at or under the 50.6 ms it cost before #986
- The text group bys that improved in #986 and #992 keep their improvement, and q9 on an int key does not move
- Every ClickBench answer is unchanged, and the pipeline, chunk agreement and SQL tests pass
- Dominant language
- Mojo
- Stars
- 3
- Forks
- 0
- Avg merge
- 9m
- Merged PRs (30d)
- 407
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from tamnd/firepanda
-
Difficulty 1/5 Under an hour Newbie friendliness 68/100
tamnd/firepanda#354 · 1 comment ·
Maintainers usually reply within 1 day
-
Soak run failingOpentest
Difficulty 3/5 1-2 days Newbie friendliness 65/100
tamnd/firepanda#1005 · 34 comments ·
Maintainers usually reply within 1 day
-
area/plan performance
Difficulty 4/5 3-5 days Newbie friendliness 45/100
tamnd/firepanda#999 · 9 comments ·
Maintainers usually reply within 1 day
-
area/arrow area/kernel area/string performance
Difficulty 5/5 Over a week Newbie friendliness 25/100
tamnd/firepanda#979 · 9 comments ·
Maintainers usually reply within 1 day
-
ci performance test
Difficulty 4/5 3-5 days Newbie friendliness 45/100
tamnd/firepanda#968 · 6 comments ·
Maintainers usually reply within 1 day
Similar issues
-
[Bug]: RDFlex silently drops the covariate adjustment when the outcome or treatment column is integer-typedPossibly taken @vrjdev claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
DoubleML/doubleml-for-py#424 ·
Maintainers usually reply within 1 day
-
Importer: an empty or non-numeric Error cell is imported as 0 instead of missingPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Open-Systems-Pharmacology/OSPSuite.Core#3049 ·
Maintainers usually reply within 1 day
-
onenote
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
obsidianmd/obsidian-importer#689 ·
-
uberon-classhierarchy
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
obophenotype/uberon#3808 · 2 comments ·
Maintainers usually reply within 1 day
-
Add DomainOpen
Difficulty 1/5 Under an hour Newbie friendliness 65/100
disposable/disposable#318 ·