Skip to content

Commit a885ffc

Browse files
committed
docs: yard routes export and benchmark section
1 parent 1058974 commit a885ffc

3 files changed

Lines changed: 2812 additions & 0 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ C++20, CMake, Arrow-like in-memory column batches, SIMD-friendly operator interf
1616
cmake -S . -B build && cmake --build build && ctest --test-dir build --output-on-failure
1717
```
1818

19+
`yard_export` writes `docs/yard/yard-routes.json`: every memo alternative for four workings, priced by the cost model and timed through vectorized execution. See the "Yard Routes" section of `docs/benchmarks.md`.
20+
1921
## Phase map
2022

2123
1. Parser, binder, logical algebra, and golden-query oracle.

‎docs/benchmarks.md‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,3 +280,114 @@ The checksum match is performed before timing and pins the left-only output
280280
and correlated candidate-set semantics. The vectorized grouped hash kernel is
281281
16.350x faster on median than the interpreted left-row-major semantic oracle
282282
for this selective workload.
283+
284+
## Yard Routes (2026-09-01)
285+
286+
`yard_export` (commit `1058974ea747`) enumerates every memo alternative for four
287+
workings, prices each with `estimate_cost`, and times each through vectorized
288+
execution with the same Release build, five-repetition min/median, deterministic
289+
data, and checksum-before-timing methodology as above. The chosen row is the
290+
`extract_best` winner; every alternative must reproduce its bag checksum. The
291+
interpreted timing is for the chosen plan only.
292+
293+
### coupling
294+
295+
```sql
296+
SELECT l.payload AS left_payload, r.payload AS right_payload FROM join_left AS l JOIN join_right AS r ON l.k1 = r.k1 AND l.k2 = r.k2
297+
```
298+
299+
memo: 4 groups, 1 iterations, fired rules: JoinCommuteRule
300+
301+
| alternative | plan | total cost | vectorized min ms | vectorized median ms |
302+
|---:|---|---:|---:|---:|
303+
| 0 (chosen) | `Project[left_payload=col(l.payload), right_payload=col(r.payload)] Join[col(l.k1) = col(r.k1) AND col(l.k2) = col(r.k2)] Scan[join_left AS l] Scan[join_right AS r]` | 200512.00 | 15.060 | 15.291 |
304+
| 1 | `Project[left_payload=col(l.payload), right_payload=col(r.payload)] Join[col(l.k1) = col(r.k1) AND col(l.k2) = col(r.k2)] Scan[join_right AS r] Scan[join_left AS l]` | 200512.00 | 15.361 | 15.564 |
305+
306+
interpreted (chosen plan): 5707.965 / 5737.780 ms; rows=100000 checksum=0xd6eff9218be6da07 bag checksum=0xe60844c222869ce8
307+
308+
### hump-and-bowl
309+
310+
```sql
311+
SELECT l.group_id AS group_id, COUNT(*) AS n, MAX(r.measure) AS top FROM e2e_left AS l JOIN e2e_right AS r ON l.k = r.k WHERE l.filter_key < 80 GROUP BY l.group_id ORDER BY n DESC, group_id ASC LIMIT 20
312+
```
313+
314+
memo: 11 groups, 2 iterations, fired rules: JoinCommuteRule, FilterIntoJoinRule, JoinCommuteRule
315+
316+
| alternative | plan | total cost | vectorized min ms | vectorized median ms |
317+
|---:|---|---:|---:|---:|
318+
| 0 (chosen) | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Filter[col(l.filter_key) < lit(80)] Join[col(l.k) = col(r.k)] Scan[e2e_left AS l] Scan[e2e_right AS r]` | 241486.08 | 27.881 | 27.934 |
319+
| 1 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Filter[col(l.filter_key) < lit(80)] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Scan[e2e_left AS l]` | 241486.08 | 25.992 | 26.419 |
320+
| 2 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Filter[col(l.filter_key) < lit(80)] Scan[e2e_left AS l] Scan[e2e_right AS r]` | 283072.00 | 24.780 | 24.812 |
321+
| 3 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Filter[col(l.filter_key) < lit(80)] Scan[e2e_left AS l]` | 283072.00 | 23.322 | 23.467 |
322+
323+
interpreted (chosen plan): 4175.083 / 4200.672 ms; rows=20 checksum=0xae466c9b0f225c78 bag checksum=0x5ad6701e8dbf32d5
324+
325+
### three-trains
326+
327+
```sql
328+
SELECT l.group_id AS group_id, COUNT(*) AS n, MAX(r.measure) AS top FROM e2e_left AS l JOIN e2e_right AS r ON l.k = r.k JOIN e2e_class AS c ON l.group_id = c.group_id WHERE c.tier = 1 GROUP BY l.group_id ORDER BY n DESC, group_id ASC LIMIT 20
329+
```
330+
331+
memo: 22 groups, 3 iterations, fired rules: JoinCommuteRule, JoinCommuteRule, JoinAssociateRule, FilterIntoJoinRule, JoinAssociateRule, JoinCommuteRule, FilterIntoJoinRule, JoinCommuteRule, JoinCommuteRule, JoinAssociateRule, JoinAssociateRule, JoinCommuteRule, FilterIntoJoinRule, JoinCommuteRule, JoinCommuteRule, JoinCommuteRule
332+
333+
| alternative | plan | total cost | vectorized min ms | vectorized median ms |
334+
|---:|---|---:|---:|---:|
335+
| 0 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Filter[col(c.tier) = lit(1)] Join[col(l.group_id) = col(c.group_id)] Join[col(l.k) = col(r.k)] Scan[e2e_left AS l] Scan[e2e_right AS r] Scan[e2e_class AS c]` | 241224.68 | 39.776 | 39.897 |
336+
| 1 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Filter[col(c.tier) = lit(1)] Join[col(l.group_id) = col(c.group_id)] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Scan[e2e_left AS l] Scan[e2e_class AS c]` | 241224.68 | 34.654 | 34.667 |
337+
| 2 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Filter[col(c.tier) = lit(1)] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_class AS c] Join[col(l.k) = col(r.k)] Scan[e2e_left AS l] Scan[e2e_right AS r]` | 241224.68 | 32.942 | 32.990 |
338+
| 3 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Filter[col(c.tier) = lit(1)] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_class AS c] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Scan[e2e_left AS l]` | 241224.68 | 30.710 | 30.725 |
339+
| 4 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Filter[col(c.tier) = lit(1)] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_left AS l] Scan[e2e_class AS c]` | 241096.68 | 36.685 | 36.737 |
340+
| 5 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Filter[col(c.tier) = lit(1)] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_class AS c] Scan[e2e_left AS l]` | 241096.68 | 32.799 | 32.900 |
341+
| 6 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Filter[col(c.tier) = lit(1)] Join[col(l.k) = col(r.k)] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_left AS l] Scan[e2e_class AS c] Scan[e2e_right AS r]` | 241096.68 | 39.762 | 39.825 |
342+
| 7 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Filter[col(c.tier) = lit(1)] Join[col(l.k) = col(r.k)] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_class AS c] Scan[e2e_left AS l] Scan[e2e_right AS r]` | 241096.68 | 29.400 | 29.418 |
343+
| 8 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.group_id) = col(c.group_id)] Join[col(l.k) = col(r.k)] Scan[e2e_left AS l] Scan[e2e_right AS r] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c]` | 241109.48 | 27.592 | 27.625 |
344+
| 9 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.group_id) = col(c.group_id)] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Scan[e2e_left AS l] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c]` | 241109.48 | 24.504 | 24.548 |
345+
| 10 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.group_id) = col(c.group_id)] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c] Join[col(l.k) = col(r.k)] Scan[e2e_left AS l] Scan[e2e_right AS r]` | 241109.48 | 25.881 | 25.902 |
346+
| 11 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.group_id) = col(c.group_id)] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Scan[e2e_left AS l]` | 241109.48 | 23.560 | 23.607 |
347+
| 12 (chosen) | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_left AS l] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c]` | 240866.28 | 16.510 | 16.563 |
348+
| 13 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Join[col(l.group_id) = col(c.group_id)] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c] Scan[e2e_left AS l]` | 240866.28 | 15.168 | 15.200 |
349+
| 14 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_left AS l] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c] Scan[e2e_right AS r]` | 240866.28 | 17.779 | 17.896 |
350+
| 15 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Join[col(l.group_id) = col(c.group_id)] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c] Scan[e2e_left AS l] Scan[e2e_right AS r]` | 240866.28 | 14.535 | 14.738 |
351+
| 16 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Filter[col(c.tier) = lit(1)] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_left AS l] Scan[e2e_class AS c]` | 240981.48 | 26.074 | 26.108 |
352+
| 17 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Filter[col(c.tier) = lit(1)] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_class AS c] Scan[e2e_left AS l]` | 240981.48 | 21.237 | 21.333 |
353+
| 18 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_left AS l] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c]` | 240866.28 | 16.506 | 16.541 |
354+
| 19 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Scan[e2e_right AS r] Join[col(l.group_id) = col(c.group_id)] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c] Scan[e2e_left AS l]` | 240866.28 | 15.267 | 15.569 |
355+
| 20 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Filter[col(c.tier) = lit(1)] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_left AS l] Scan[e2e_class AS c] Scan[e2e_right AS r]` | 240981.48 | 26.842 | 26.997 |
356+
| 21 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Filter[col(c.tier) = lit(1)] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_class AS c] Scan[e2e_left AS l] Scan[e2e_right AS r]` | 240981.48 | 20.516 | 20.581 |
357+
| 22 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Join[col(l.group_id) = col(c.group_id)] Scan[e2e_left AS l] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c] Scan[e2e_right AS r]` | 240866.28 | 17.074 | 17.142 |
358+
| 23 | `Limit[20] Sort[col(n) DESC, col(group_id) ASC] Project[group_id=col(l.group_id), n=col(COUNT(*)), top=col(MAX(r.measure))] Aggregate[group_keys=[col(l.group_id)], aggregates=[COUNT(*), MAX(r.measure)=col(r.measure)]] Join[col(l.k) = col(r.k)] Join[col(l.group_id) = col(c.group_id)] Filter[col(c.tier) = lit(1)] Scan[e2e_class AS c] Scan[e2e_left AS l] Scan[e2e_right AS r]` | 240866.28 | 14.410 | 14.423 |
359+
360+
interpreted (chosen plan): 1591.984 / 1601.294 ms; rows=20 checksum=0x7e53943623dc6b01 bag checksum=0x8f1c966523a83a50
361+
362+
### special
363+
364+
```sql
365+
SELECT l.payload AS payload FROM join_left AS l WHERE l.k1 IN (SELECT r.k1 FROM join_right AS r WHERE r.payload = 10000)
366+
```
367+
368+
memo: 7 groups, 1 iterations, fired rules: InToSemiJoinRule
369+
370+
| alternative | plan | total cost | vectorized min ms | vectorized median ms |
371+
|---:|---|---:|---:|---:|
372+
| 0 (chosen) | `Project[payload=col(l.payload)] Filter[col(l.k1) IN subquery(IN subquery at position 59)] Subquery[IN subquery at position 59] Project[r.k1=col(r.k1)] Filter[col(r.payload) = lit(10000)] Scan[join_right AS r] Scan[join_left AS l]` | 200512.00 | 3.063 | 3.151 |
373+
| 1 | `Project[payload=col(l.payload)] SemiJoin[col(l.k1) = col(r.k1)] Scan[join_left AS l] Project[r.k1=col(r.k1)] Filter[col(r.payload) = lit(10000)] Scan[join_right AS r]` | 200537.60 | 5.250 | 5.272 |
374+
375+
interpreted (chosen plan): 8.902 / 9.068 ms; rows=6250 checksum=0x72a0d9bc69515c7e bag checksum=0x5b144f1cb20c62ff
376+
377+
### hump workloads
378+
379+
| workload | predicate | kept | interpreted min ms | interpreted median ms | vectorized min ms | vectorized median ms |
380+
|---|---|---:|---:|---:|---:|---:|
381+
| scan_filter_1pct | `bucket = 7` | 2000 | 17.409 | 17.525 | 7.904 | 7.949 |
382+
| scan_filter_10pct | `decile = 3` | 20000 | 18.751 | 18.816 | 9.067 | 9.089 |
383+
| scan_filter_50pct | `half = 1` | 100000 | 25.338 | 25.427 | 14.235 | 14.249 |
384+
385+
### three_way_route in sql_bench
386+
387+
The three-trains working is also registered in `sql_bench` as `three_way_route`, timed on the
388+
query as bound (the first alternative above, before the memo reorders it). Same Release build,
389+
five repetitions, checksum before timing:
390+
391+
| workload | rows | correctness | interpreted min ms | interpreted median ms | vectorized min ms | vectorized median ms | median speedup |
392+
|---|---:|---|---:|---:|---:|---:|---:|
393+
| three_way_route | left=120000,right=256,class=128 | match rows=20 checksum=0x7e53943623dc6b01 | 5829.809 | 5843.328 | 39.476 | 39.516 | 147.871x |

0 commit comments

Comments
 (0)