mirror of
https://github.com/addyosmani/agent-skills.git
synced 2026-10-26 15:05:04 +00:00
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:
1 parent
0ce0107f4f
commit
bfc9e32ddf
2 files changed
+5
-5
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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 |
|
||||
|
||||
Reference in new issue
Block a user