Začněte s plánem dotazu, pak opravte největší náklady. Použijte EXPLAIN/ abyste viděli, co databáze skutečně dělá, přidejte správné , eliminujte dotazy a vyberte si pouze data, která potřebujete.
Začněte s plánem dotazu, pak opravte největší náklady. Použijte EXPLAIN/ abyste viděli, co databáze skutečně dělá, přidejte správné , eliminujte dotazy a vyberte si pouze data, která potřebujete.
EXPLAIN ANALYZEEXPLAIN ANALYZE ukazuje plán spuštění a reálné časy. Seq Scan přes velkou tabulku je klasický varovný signál:
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!
Index změní úplné skenování na rychlé vyhledávání:
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
Indexy mají náklady na zápisy: každý INSERT/UPDATE musí také aktualizovat index, takže indexujte sloupce, podle kterých filtrujete/spojujete/řadíte — ne každý sloupec. Složený index (customer_id, created_at) obslouží WHERE customer_id = ? ORDER BY created_at v jedné struktuře.
N+1 problém — jeden dotaz na seznam, pak jeden na řádek — je hlavní příčinou pomalosti. Nahraďte jej eager loadingem, JOIN nebo dávkovým 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;
Také vyberte pouze potřebné sloupce (vyhněte se SELECT *) a stránkujte pomocí LIMIT/keyset paginace, abyste nikdy nenačetli miliony řádků.
Databáze je nejčastějším úzkým místem. Čtení plánu vám řekne, proč je dotaz pomalý, místo aby ste hádat; správný index, odstranění N+1 a oříznutí sady výsledků rutinně změní dotazy trvající sekundy na dotazy trvající milisekundy — bez rozšíření hardwaru.