Start med spørsmålsplanen, og fiks deretter den største kostnaden. Bruk EXPLAIN/EXPLAIN ANALYZE for å se hva databasen faktisk gjør, legg til de riktige indeksene, eliminer N+1 spørringer, og velg bare dataene du trenger.
Les spørsmålsplanen
EXPLAIN ANALYZE viser kjøreplanen og faktiske timinger. En Seq Scan over en stor tabell er det klassiske rødt flagget:
EXPLAIN ANALYZE
SELECT * FROM orders WHERE customer_id = 42;
-- Seq Scan on orders (cost=0.00..18500 rows=120)
-- Filter: (customer_id = 42)
-- rows removed by filter: 999880 ← scanned the whole table!
Legg til riktig indeks
En indeks gjør en full scanning til et raskt oppslag:
CREATE INDEX idx_orders_customer ON orders (customer_id);
-- Now: Index Scan using idx_orders_customer (cost=0.42..8.5 rows=120)
-- 1,000,000-row scan → ~120-row lookup
Indekser har en kostnad ved skriving: hver INSERT/UPDATE må også oppdatere indeksen, så indekser kolonnene du filtrerer/sammenføyer/sorterer på — ikke hver kolonne. En sammensatt indeks (customer_id, created_at) betjener WHERE customer_id = ? ORDER BY created_at i en struktur.
Fiks N+1 og over-henting
N+1-problemet — ett spørsmål for en liste, deretter ett per rad — er en toppårsak til treghet. Erstatt det med eager loading, en JOIN, eller batched IN (...):
-- N+1: 1 + 100 queries
SELECT * FROM orders; -- then per order: SELECT * FROM users WHERE id = ?
-- Fixed: one JOIN, only needed columns
SELECT o.id, o.total, u.name
FROM orders o JOIN users u ON u.id = o.user_id;
Velg også bare nødvendige kolonner (unngå SELECT *) og paginer med LIMIT/keyset pagination slik at du aldri laster inn millioner av rader.
Hvorfor det betyr noe
Databasen er den vanligste flaskehalsen. Å lese planen forteller deg hvorfor et spørsmål er tregt i stedet for å gjette; riktig indeks, fjerning av N+1, og trimming av resultatsettet gjør rutinemessig spørringer som tar sekunder om til millisekunder — uten å skalere maskinvare.
