shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 10000
pg_stat_statements.track = all
# บันทึก Query ที่ช้ากว่าหนึ่งวินาที
log_min_duration_statement = 1000
log_checkpoints = on
log_lock_waits = on
log_temp_files = 0
sudo systemctl restart postgresql
sudo -u postgres psql -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements;"
ขั้นตอนที่ 7: วัดผล
-- Query ที่ใช้เวลารวมมากที่สุด
SELECT substr(query, 1, 80) AS query,
calls,
round(total_exec_time::numeric, 0) AS total_ms,
round(mean_exec_time::numeric, 2) AS mean_ms,
rows
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 15;
-- อัตราการอ่านจากแคช ควรสูงกว่า 99% สำหรับระบบที่ปรับดีแล้ว
SELECT datname,
round(100.0 * blks_hit / NULLIF(blks_hit + blks_read, 0), 2) AS cache_hit_pct
FROM pg_stat_database
WHERE datname NOT IN ('template0','template1');
-- ตารางที่มีแถวตายสะสมมาก
SELECT relname, n_live_tup, n_dead_tup,
round(100.0 * n_dead_tup / NULLIF(n_live_tup + n_dead_tup, 0), 1) AS dead_pct,
last_autovacuum
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC;
ล้างสถิติเพื่อเริ่มวัดรอบใหม่หลังปรับค่า
SELECT pg_stat_statements_reset();
ขั้นตอนที่ 8: ตรวจการใช้ Index
-- Index ที่ไม่เคยถูกใช้
SELECT schemaname, relname, indexrelname, idx_scan,
pg_size_pretty(pg_relation_size(indexrelid)) AS size
FROM pg_stat_user_indexes
WHERE idx_scan = 0
ORDER BY pg_relation_size(indexrelid) DESC;
-- ตารางที่ถูกสแกนทั้งตารางบ่อย
SELECT relname, seq_scan, seq_tup_read, idx_scan,
round(seq_tup_read::numeric / NULLIF(seq_scan, 0), 0) AS avg_rows_per_scan
FROM pg_stat_user_tables
WHERE seq_scan > 100
ORDER BY seq_tup_read DESC LIMIT 10;