feat(bench): Group B workloads — W7..W9 (sub-phase 9.3)#104
Merged
Conversation
Lands the SQL-feature-scaling workloads on top of the 9.2 Group A
baseline:
W7 aggregate SELECT SUM(v) FROM big over 1M rows.
Single-statement full-scan + accumulator.
W8 group-by SELECT k, COUNT(*) FROM big GROUP BY k at three
cardinalities (10 / 1k / 100k distinct groups).
Each cardinality is its own criterion group.
W9 inner-join customers ⨝ orders ON c.id = o.customer_id,
per-PK-probe shape, single matching order per
customer.
Two notable plan deviations land alongside the workloads, both
captured in code + README:
W8 / 100k-cardinality on SQLRite — skipped by default. A first
measurement clocked ~245 s per criterion iteration (~41 min for
10 samples), strongly suggesting an O(n × cardinality) GROUP BY
path. Setting `SQLRITE_BENCH_W8_CARD_100K_SQLRITE=1` re-enables
the bucket. SQLR-19 tracks the investigation. SQLite runs the
same bucket fine.
W9 dataset scaled 100k rows → 10k rows. Plan target was two
100k-row tables, but a first smoke ran 88 minutes on SQLRite
without producing a single sample. SQLRite's join executor
(`src/sql/executor.rs::execute_select_rows_joined`) is a
left-folded nested-loop driver with no inner-side index probe,
so per-PK probe walks every row in `orders`. SQLR-20 tracks
the planner / index-pushdown fix; bumping back to 100k follows
that + a `W9.v2` tag.
Smoke run (M1 Pro, criterion --warm-up-time 1 --measurement-time 1
--sample-size 10):
W7 sqlrite ~111 ms / sqlite ~31 ms — ~3.5x
W8 card-10 sqlrite ~204 ms / sqlite ~460 ms — sqlrite wins (small samples;
SQLite picks sort-then-group)
W8 card-1k sqlrite ~1.50 s / sqlite ~242 ms — ~6.2x
W8 card-100k sqlrite SKIPPED / sqlite ~241 ms — ⚠ SQLR-19
W9 (10k) sqlrite ~32 s / sqlite ~2.3 us — ~14_000_000x ⚠ SQLR-20
W7's ~3.5x is the *closest* SQLRite has come to SQLite on any
workload — the per-row "touch" cost in the executor is tighter
than the per-iter parse cost dominates W1 / W6. Encouraging
signal for the executor itself.
Verification:
- cargo fmt --all -- --check clean
- cargo clippy -p sqlrite-benchmarks --all-targets clean
- Full CI-equivalent build / test / doc green
(--exclude desktop / python / nodejs / benchmarks)
- Smoke run end-to-end across W7..W9 + aggregator → JSON envelope
Refs: SQLR-16 (parent), SQLR-19 (W8 high-cardinality),
SQLR-20 (W9 join planner).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 7, 2026
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.
Summary
Sub-phase 9.3 of
docs/benchmarks-plan.md. Builds on #102 (9.1 harness + W1) and #103 (9.2 Group A) to land the SQL-feature-scaling workloads:SELECT SUM(v) FROM bigover 1M rowsSELECT k, COUNT(*) FROM big GROUP BY kat 10 / 1k / 100k cardinalitiesSmoke-run numbers (M1 Pro, criterion
--warm-up-time 1 --measurement-time 1 --sample-size 10)W7's ~3.5× is the closest SQLRite has come to SQLite on any workload — the executor's per-row "touch" cost is tighter than the per-iter parse cost that dominates W1 / W6. Encouraging signal.
Two plan deviations, both documented + tracked
W8 × 100k-cardinality on SQLRite — skipped by default
A first measurement clocked ~245 s per iteration (~41 min for 10 samples) on SQLRite. Set
SQLRITE_BENCH_W8_CARD_100K_SQLRITE=1to re-enable once fixed. SQLite runs the same bucket fine.The 245 s ≈ 1M × 100k = 1e11 ops timing strongly suggests an O(n × cardinality) GROUP BY path — likely a
Vec-backed group store doing linear scans per row instead of an O(1) hash lookup. SQLR-19 tracks the investigation.W9 dataset scaled down: 100k rows → 10k rows
Plan target was two 100k-row tables. A first smoke ran 88 minutes on SQLRite without producing a single sample before being killed. SQLRite's join executor (
src/sql/executor.rs::execute_select_rows_joined) is a left-folded nested-loop driver with no inner-side index probe — so per-PK probe walks every row inorders. SQLR-20 tracks the planner / index-pushdown fix.At the reduced 10k scale, the gap is still ~14 million×:
That ~3 ms/row is 3,000× slower than W2's full-scan rate (1 µs/row). Two unlocks: (a) push the ON predicate into an index probe, (b) trim the per-pair scope-construction overhead.
Bumping W9 back to 100k follows the SQLR-20 fix + a
W9.v2tag. Plan deviation captured inbenchmarks/src/data.rs(JOIN_ROW_COUNTconst + comment) andbenchmarks/src/workloads/join.rs(top-of-file "Plan deviation" section).Test plan
cargo fmt --all -- --checkcleancargo clippy -p sqlrite-benchmarks --all-targetscleancargo build / test / doc --workspace --exclude {desktop,python,nodejs,benchmarks}greencargo test -p sqlrite-benchmarks— 5 tests pass (4 inliner + 1 ymd round-trip)cargo bench -p sqlrite-benchmarks --bench suite -- --warm-up-time 1 --measurement-time 1 '^W[789]'runs all three workloads end-to-end on both engines (with documented skips)Follow-ups
Vec→HashMapgroup store swap.<col> = <literal>fast-path; the join executor needs to reuse it.References
docs/benchmarks-plan.mdbenchmarks/src/workloads/{aggregate,group_by,join}.rs🤖 Generated with Claude Code