Πώς βλέπουμε πόσο γίνονται χρήση τα Indexes στη PostgreSQL

- Πώς βλέπουμε πόσο γίνονται χρήση τα Indexes στη PostgreSQL - 4 Σεπτέμβριος 2026
- Πώς βρίσκουμε το μέγεθος των πινάκων σε βάση δεδομένων PostgreSQL - 2 Σεπτέμβριος 2026
- Πώς ελέγχουμε τα δικαιώματα, Grants και Default Privileges σε PostgreSQL - 31 Αύγουστος 2026
Σε κάθε βάση δεδομένων, τα indexes είναι απαραίτητα για την ταχύτητα των SELECT queries. Ωστόσο, κάθε index που δημιουργούμε έχει ένα κόστος, καταλαμβάνει χώρο στο δίσκο, επιβαρύνει τη μνήμη και καθυστερεί τα INSERT, UPDATE και DELETE operations, αφού η PostgreSQL πρέπει να ενημερώνει και το index σε κάθε αλλαγή.
Για να διατηρούμε τη βάση μας καθαρή και γρήγορη, πρέπει να παρακολουθούμε συστηματικά ποια indexes χρησιμοποιούνται ενεργά και ποια παραμένουν ανενεργά επιβαρύνοντας το σύστημα.
Το query:
Το παρακάτω query επιστρέφει όλα τα indexes της βάσης (Primary Keys, Unique constraints και Regular indexes), ταξινομημένα ανά πίνακα.
Υπολογίζει το μέγεθος κάθε index σε GB, το Cache Hit Ratio % (πόσο το index εξυπηρετείται από τη RAM vs τον δίσκο), ενώ βάζει και αυτόματο Usage Status:
SELECT
i.schemaname AS schema_name,
i.relname AS table_name,
i.indexrelname AS index_name,
CASE
WHEN idx.indisprimary THEN 'PRIMARY KEY'
WHEN idx.indisunique THEN 'UNIQUE'
ELSE 'REGULAR'
END AS index_type,
i.idx_scan AS total_scans,
i.idx_tup_read AS rows_read,
i.idx_tup_fetch AS rows_fetched,
ROUND((pg_relation_size(i.indexrelid)::numeric / 1073741824.0), 3) AS index_size_gb,
CASE
WHEN (io.idx_blks_read + io.idx_blks_hit) > 0
THEN ROUND((100.0 * io.idx_blks_hit / (io.idx_blks_read + io.idx_blks_hit))::numeric, 2)
ELSE 0.00
END AS cache_hit_pct,
CASE
WHEN i.idx_scan = 0 AND NOT idx.indisprimary AND NOT idx.indisunique THEN '❌ UNUSED'
WHEN i.idx_scan = 0 THEN '⚠️ UNUSED (PK/Unique)'
WHEN i.idx_scan < 50 THEN 'ℹ️ LOW USAGE'
ELSE '✅ ACTIVE'
END AS usage_status
FROM pg_stat_user_indexes i
JOIN pg_index idx ON idx.indexrelid = i.indexrelid
LEFT JOIN pg_statio_user_indexes io ON io.indexrelid = i.indexrelid
WHERE i.schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY i.relname ASC, idx.indisprimary DESC, i.indexrelname ASC;

Τι κοιτάμε για να βγάλουμε συμπέρασμα:
ACTIVE (total_scans > 50): Το index χρησιμοποιείται τακτικά από τα queries της εφαρμογής.
UNUSED (total_scans = 0): Regular secondary index που δεν έχει χρησιμοποιηθεί ποτέ από τη δημιουργία του ή από το τελευταίο reset των στατιστικών. Αν ο πίνακας δέχεται συχνά INSERT/UPDATE, το συγκεκριμένο index μπορεί να διαγραφεί (DROP INDEX CONCURRENTLY), καθώς προσφέρει μόνο καθυστέρηση και πιάνει χώρο.
UNUSED (PK/Unique): Αχρησιμοποίητο index που όμως αντιστοιχεί σε Primary Key ή Unique Constraint. Δεν το διαγράφουμε ποτέ, καθώς διασφαλίζει το data integrity της βάσης δεδομένων.
Cache Hit Ratio: Τιμές κοντά στο 100% σημαίνουν ότι το index χωράει και διαβάζεται απευθείας από τη μνήμη RAM. Χαμηλότερα ποσοστά δείχνουν ότι η Postgres αναγκάζεται να διαβάσει απο τον δίσκο.

