fix(performance): scope low-selectivity caveat, make coalescing snippet generic

Review feedback from @federicobartoli on #521.

The low-selectivity rows read as if indexing a skewed column never
helps. That holds only when querying the dominant value; filtering on
the rare value is exactly the case a partial index serves. Scoped both
the SKILL.md table row and the checklist item.

loadOnce referenced an undeclared Row type. Made it generic so it
typechecks when pasted as-is.

Claude-Session: https://claude.ai/code/session_01TuWNaEV9RFXpTxqeBRTRg8
This commit is contained in:
Joan Leon committed 2026-08-27 20:52:22 +02:00
1 parent 0ce0107f4f
commit bfc9e32ddf
2 files changed
+5 -5

No files matched your search

+4 -4
View File
@@ -104,7 +104,7 @@ When TTFB is slow (> 800ms), check each component in DevTools Network waterfall:
- [ ] Composite index column order is equality first, then range/sort
- [ ] Index covers the query shape (filter + sort), not just one column in isolation
- [ ] Covering index considered for hot read paths (index-only scan avoids the heap fetch)
- [ ] Not indexing low-selectivity columns (one value dominating the table)
- [ ] Not indexing low-selectivity columns *for the dominant value*; a partial index still serves the rare-value query (`WHERE status = 'failed'`)
- [ ] Expression index used where the query applies a function (`lower(email)`)
- [ ] Full-text or trigram index used for leading-wildcard search, not a B-tree
- [ ] Write cost measured on write-heavy tables (every index taxes every `INSERT`/`UPDATE`)
@@ -156,10 +156,10 @@ Cache the *absence* of a result too. A key that misses on every lookup (a nonexi
One recompute, N waiters. Prevents a hot key's expiry from delivering the full concurrent load to the origin:
```typescript
const inFlight = new Map<string, Promise<Row>>();
const inFlight = new Map<string, Promise<unknown>>();
function loadOnce(key: string, fetcher: () => Promise<Row>): Promise<Row> {
const existing = inFlight.get(key);
function loadOnce<T>(key: string, fetcher: () => Promise<T>): Promise<T> {
const existing = inFlight.get(key) as Promise<T> | undefined;
if (existing) return existing;
const p = fetcher().finally(() => inFlight.delete(key));
inFlight.set(key, p);
+1 -1
View File
@@ -177,7 +177,7 @@ CREATE INDEX idx_tasks_owner_created ON tasks (owner_id, created_at DESC);
| Situation | Why |
|---|---|
| Low selectivity (a `status` column that is 95% one value) | A sequential scan is genuinely cheaper; the planner will ignore the index |
| Low selectivity, querying the dominant value (a `status` column that is 95% `active`, filtered on `active`) | A sequential scan is genuinely cheaper; the planner will ignore the index. Filtering on the rare value is the opposite case, and a partial index serves it well |
| Leading wildcard (`LIKE '%term'`) | A B-tree cannot seek without a prefix; needs trigram or full-text |
| Function on the column (`WHERE lower(email) = ?`) | The plain column index is unusable; index the expression instead |
| Write-heavy table | Every index is a tax on every `INSERT`/`UPDATE`; measure the write cost, not just the read gain |