Repository navigation
perf(db): R.4 — desc nulls last, swept and measured site by site - #318
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
Willi363363
force-pushed
the
perf/desc-nulls-last-sweep
branch
from
September 18, 2026 11:33
fca3fb5 to
3b32680
Compare
`09-query-debt.md` asked for the sweep H.2 could not do in passing: every
`.desc()` in an index, against every query that orders on it. Four indexes are
written `DESC NULLS LAST`; two of their queries already matched. The other two
were probed one at a time, on fifty thousand leaderboard entries and twenty-five
thousand coin movements.
coins.ts the ledger read 3.3 ms → 1.5 ms Bitmap Heap Scan + Sort
became Index Scan +
Incremental Sort
account.ts the export 1.2 ms → 0.5 ms the sort disappears
leaderboard.ts all-time 26.5 ms → 26.5 ms unchanged, left alone
daily-board.ts the day 6.3 ms → 6.3 ms unchanged, left alone
Only the two that moved are changed, which is what the register asked for: a
query fixed on the strength of another query's number is the guess it exists to
refuse. `daily-board.ts` filters on `game.daily_day` and never on the entry's
`mode`, so the partial index cannot serve it whatever the ordering says.
**The register's own 45 ms → 26 ms does not reproduce, and the entry is
corrected.** All four spellings of the all-time board — inner, outer, both,
neither — measured 26.5 to 27.1 ms with identical plans, and identical again
with `enable_seqscan` off. The board is `distinct on (user_id)` since G.7, so
its ordering starts with `user_id` and no index starts there and continues with
`score`. The 19 ms belongs to that deduplication, not to an ordering.
The spelling is one constant, exported from `coins.ts` and used by
`exportAccount`: an order that has to match an index in two files is one source
of truth or it comes back in whichever file is edited second.
Both new cases fail with the bare `desc` put back — the plan one because the
index is no longer reachable, the SQL one because the text is no longer written.
`turbo run test --force --concurrency=1`: 10 of 10 tasks, 3 866 passed, 0
skipped. Typecheck and lint green over all 22 tasks.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DsMRxyowr2Ch5RwiAa3t9z
Willi363363
force-pushed
the
perf/desc-nulls-last-sweep
branch
from
September 18, 2026 11:54
3b32680 to
5147417
Compare
This branch was successfully deployed
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.
Fourth and last step of track R, rebased on
stagingand carrying its ownR.4 ⬜ → ✅tick. Independent of #315, #316 and #317 in code — but it editsthe same register file, see Before merging.
09-query-debt.mdasked for the sweep H.2 could not do in passing: "every.desc()in an index, against every query that orders on it". Four indexes arewritten
DESC NULLS LAST; two of their queries already matched, found by H.2and by K. The other two were probed one at a time.
Measured, site by site
Fifty thousand leaderboard entries over two thousand players, and twenty-five
thousand coin movements over two accounts. Median of seven
explain (analyze)runs each.
coins.tsthe ledger readaccount.tsthe exportleaderboard.tsall-time boarddaily-board.tsthe day's boardOnly the two that moved are changed. That is the discipline the register
asks for: a query fixed on the strength of another query's number is exactly the
guess it exists to refuse.
daily-board.tsfilters ongame.daily_dayand neveron the entry's
mode, so the partial(mode, score desc, …)index cannot serveit whatever the ordering says.
The ledger's sort becomes incremental rather than disappearing because it also
orders on
seq, which no index carries besidecreated_at— the tie inside onecreated_atstill sorts.The register's own number was wrong, and is corrected
09-query-debt.mdclaimed the all-time board went 45 ms → 26 ms by changingone ordering. It does not reproduce. All four spellings — inner, outer, both,
neither — measured 26.5 to 27.1 ms on the same seed, with identical plans, and
identical again with
enable_seqscanoff.The reason is G.7: the board is
distinct on (user_id)now, so its orderingstarts with
user_id, and no index starts there and continues withscore.The 19 ms was recovered by that deduplication, not by the ordering — and the row
was written before that shape existed. Corrected in place rather than deleted,
because a number that turned out to belong to something else is the thing this
register is for.
One spelling, not two
newestClockFirstis exported fromcoins.tsand used byexportAccount. Anorder that has to match an index in two files is one source of truth or it is
the same defect coming back in whichever file is edited second.
Tests
Two cases in
coins-volume.test.ts, both failing with the baredescputback — the plan one because the index is no longer reachable with
seqscanandbitmapscanoff, the SQL one because the text is no longer written.Checks
turbo run test --force --concurrency=1: 10 of 10 tasks, 3 866 passed, 0 skipped.turbo run typecheck lint --force: 22 of 22.pnpm format:check: green.Before merging
#316 and #317 also edit
09-query-debt.md, which is at its 200-line cap. On thisbranch the file is 195; on top of those two it will be over. Whichever merges
last gets rebased and re-trimmed, and the register is due a split either way —
recorded rather than done here, since it is not this step.
🤖 Generated with Claude Code
https://claude.ai/code/session_01DsMRxyowr2Ch5RwiAa3t9z