1-- TASK-0135 perf hot-path indexes, round 2 (EXPLAIN-proven; see 2-- docs/development/perf-report.md §3). Companion to 3-- 20261003210000_perf_indexes_hot_paths (audit + file listing). 4-- 5-- The first round only covered the audit-listing and file-listing queries. A 6-- follow-up EXPLAIN (ANALYZE, BUFFERS) pass over the remaining top-5 queries 7-- found TWO more Sort nodes no index served: 8-- 9-- 1. Page tree load (depth=all — the "< 2 s for 100k blocks" path): 10-- SELECT * FROM blocks WHERE "pageId"=$1 AND "deletedAt" IS NULL 11-- ORDER BY "position" ASC LIMIT 1000 12-- Before: Bitmap Heap Scan (blocks_workspaceId_pageId_idx, 10k rows) + 13-- top-N heapsort — 12.7 ms on the 10k-block seed page. 14-- After: backward-free Index Scan on (pageId, position) — 0.67 ms, 15-- Sort node GONE. The existing (pageId, parentId, position) index cannot 16-- serve a parentId-less range in position order, and 17-- (workspaceId, pageId) has no position key at all. 18-- 19-- 2. 100k-record database table list: 20-- SELECT * FROM database_records WHERE "databaseId"=$1 21-- AND "archivedAt" IS NULL ORDER BY "position" ASC LIMIT 50 22-- Before: parallel Bitmap Heap Scan (databaseId, archivedAt) + Gather 23-- Merge + Sort — 170 ms on the 100k seed DB. 24-- After: Index Scan on (databaseId, position) — 0.16 ms, Sort node 25-- GONE. (databaseId, archivedAt) prunes archived rows but offers no 26-- position ordering; the low-selectivity archivedAt filter is applied as 27-- an index recheck. 28-- 29-- No speculative indexes: every one here is tied to a named query + a 30-- before/after EXPLAIN in the report. 31 32CREATE INDEX IF NOT EXISTS "blocks_pageId_position_idx" 33 ON "blocks" ("pageId", "position"); 34 35CREATE INDEX IF NOT EXISTS "database_records_databaseId_position_idx" 36 ON "database_records" ("databaseId", "position"); 37