Ξεκίνησε με το query plan, μετά διόρθωσε το μεγαλύτερο κόστος. Χρησιμοποίησε / για να δεις τι κάνει στην πραγματικότητα η βάση δεδομένων, πρόσθεσε τα σωστά , εξάλειψε τα ερωτήματα, και επίλεξε μόνο τα δεδομένα που χρειάζεσαι.
Ξεκίνησε με το query plan, μετά διόρθωσε το μεγαλύτερο κόστος. Χρησιμοποίησε / για να δεις τι κάνει στην πραγματικότητα η βάση δεδομένων, πρόσθεσε τα σωστά , εξάλειψε τα ερωτήματα, και επίλεξε μόνο τα δεδομένα που χρειάζεσαι.
EXPLAINEXPLAIN ANALYZEΤο EXPLAIN ANALYZE δείχνει το execution plan και τα πραγματικά χρονικά διαστήματα. Ένα Seq Scan σε έναν μεγάλο πίνακα είναι το κλασικό κόκκινο σήμα:
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 μετατρέπει ένα πλήρες scan σε γρήγορη αναζήτηση:
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
Τα indexes έχουν κόστος στις εγγραφές: κάθε INSERT/UPDATE πρέπει επίσης να ενημερώσει το index, επομένως δημιούργησε index στις στήλες που φιλτράρεις/συνδέεις/ταξινομείς — όχι σε κάθε στήλη. Ένα composite index (customer_id, created_at) εξυπηρετεί WHERE customer_id = ? ORDER BY created_at σε μία δομή.
Το N+1 πρόβλημα — ένα ερώτημα για μια λίστα, μετά ένα ανά σειρά — είναι μια κορυφαία αιτία αργής απόδοσης. Αντικαταστήστε το με eager loading, ένα JOIN, ή 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;
Επίσης επίλεξε μόνο τις απαραίτητες στήλες (αποφύγετε SELECT *) και δημιούργησε pagination με LIMIT/keyset pagination ώστε να μην φορτώσεις ποτέ εκατομμύρια σειρών.
Η βάση δεδομένων είναι το πιο συνηθισμένο bottleneck. Η ανάγνωση του plan σε λέει γιατί ένα ερώτημα είναι αργό αντί να το μαντεύεις. το σωστό index, η αφαίρεση N+1, και η περικοπή του result set συνήθως μετατρέπουν ερωτήματα που διαρκούν δεύτερα σε ερωτήματα που διαρκούν χιλιοστά του δευτερολέπτου — χωρίς να χρειαστεί να κλιμακώσεις hardware.