#171: defer the lite join off the substrate filter-build critical path#333
Merged
Conversation
…d critical path
Benchmark 2026-07-11 caught it (Codex-verified mechanism): the substrate
builder joined EVERY matched pid to the remote lite parquet for display
fields only the 50 panel rows need — making big-result queries (bare
'pottery', 42,541 matches: 57.4s cold) SLOWER than the baseline they
replace. The interim path never pays this because it reads display
fields from the same file it already scanned.
search_pids from the substrate now carries pid + relevance_score with
NULL display columns (schema unchanged); every consumer joins lite and
reads COALESCE(s.*, l.*), so interim rows keep their own values:
- area panel: already join→filter→LIMIT; display fields COALESCEd
- world panel: restructured to join lite BEFORE filter/LIMIT (the
source filter must see l.source when s.source is NULL); Codex's
filters-before-LIMIT condition holds in both shapes
- world follow-up COUNT: gains the lite LEFT JOIN for the same reason
- sourceSQL snapshot: sourceFilterSQL("COALESCE(s.source, l.source)")
facetFilterSQL is pid-IN-based (verified) — unaffected by NULL columns.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AjnkWb4HpuLeDbYfzmY3X9
…rate+source-filter Codex round-2 blocker on the deferral: the join-everything restructure taxed the INTERIM path with a full-match-set lite join it never had (bare 'bone' interim = 543k-row join) and changed tie selection. The expensive join-before-limit shape is now used ONLY when it's actually required — a substrate search (NULL s.source) under an ACTIVE source filter. Interim searches and unfiltered substrate searches keep the original CTE: filter + LIMIT 50 on search_pids, then join lite for just those 50 (COALESCE handles substrate NULL display fields). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AjnkWb4HpuLeDbYfzmY3X9
rdhyee
added a commit
to rdhyee/isamplesorg.github.io
that referenced
this pull request
Jul 11, 2026
…every row Substrate side re-measured against prod after PR isamplesorg#333. The former outlier (bare 'pottery', 42,541 results: 57.4s) is now 11.6s cold — substrate beats baseline on every query, typically ~2x cold, with no-hit at 8.5s vs 62.7s. All label-free cross-checks still pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AjnkWb4HpuLeDbYfzmY3X9
8 tasks
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.
What this does
The 2026-07-11 benchmark's outlier — bare
pottery(42,541 results) substrate-slower-than-baseline — was caused by the substrate builder joining EVERY matched pid to the remote lite parquet for display fields only the 50 panel rows need. Now:search_pids= pid + score (+ NULL display columns, shared 5-col shape preserved)s.sourceis NULL); interim and unfiltered-substrate searches keep the original 50-row-join CTE (round-2 blocker fix)Measured (preview, fresh context)
potteryfilter publish: ~40s → 825 ms; panel with real labels at 7.2s; count exact (42,541); source-filtered substrate panel verified all-OpenContext; 6/6 e2e (incl. default-path non-regression), 110/110 unit, 0 console errors.Codex rounds: 1 endorsed mechanism → round 2 blocker (interim regression — real) → fixed → round 3 LGTM.
Refs #171 (benchmark re-run of affected rows to follow post-merge).
🤖 Generated with Claude Code
https://claude.ai/code/session_01AjnkWb4HpuLeDbYfzmY3X9