Back to Blog

PostgreSQL Monitoring: A Complete Guide to Database Observability

TheDBAdmin Team4 min read
PostgreSQL Monitoring: A Complete Guide to Database Observability

Master PostgreSQL monitoring with this comprehensive guide covering essential metrics, tools like Prometheus and Grafana, query performance analysis, and best practices for maintaining database health.

Effective monitoring is crucial for maintaining healthy PostgreSQL databases. This comprehensive guide covers everything you need to know about monitoring PostgreSQL, from basic metrics to advanced monitoring strategies.

Table of Contents

  1. Essential PostgreSQL Metrics
  2. Monitoring Tools
  3. Query Performance Monitoring
  4. System Resource Monitoring
  5. Alerting Strategies
  6. Best Practices

Essential PostgreSQL Metrics

1. Connection Metrics

sql
-- Monitor active connections
SELECT count(*), state 
FROM pg_stat_activity 
GROUP BY state;

-- Check connection utilization
SELECT 
    current_setting('max_connections')::int as max_conn,
    count(*) as current_conn,
    (count(*)::float/current_setting('max_connections')::int * 100)::int 
    as conn_percent 
FROM pg_stat_activity;

2. Database Size and Growth

sql
-- Monitor database sizes
SELECT 
    datname,
    pg_size_pretty(pg_database_size(datname)) as size,
    pg_size_pretty(pg_database_size(datname) - 
        coalesce(previous_size, 0)) as growth
FROM pg_database;

-- Table growth monitoring
SELECT 
    schemaname,
    relname,
    n_live_tup as row_count,
    pg_size_pretty(pg_total_relation_size(schemaname || '.' || relname)) as total_size
FROM pg_stat_user_tables
ORDER BY pg_total_relation_size(schemaname || '.' || relname) DESC;

3. Transaction Metrics

sql
-- Transaction statistics
SELECT 
    datname,
    xact_commit,
    xact_rollback,
    (xact_rollback::float / (xact_commit + xact_rollback) * 100)::numeric(10,2) 
    as rollback_ratio
FROM pg_stat_database;

Monitoring Tools

1. Prometheus with PostgreSQL Exporter

Example prometheus.yml configuration:

yaml
scrape_configs:
  - job_name: 'postgresql'
    static_configs:
      - targets: ['localhost:9187']
    metrics_path: '/metrics'

Example queries:

promql
# Query rate of transactions
rate(pg_stat_database_xact_commit{datname="mydb"}[5m])

# Database size
pg_database_size_bytes{datname="mydb"}

# Connection utilization
pg_stat_activity_count / pg_settings_max_connections * 100

2. Grafana Dashboard Setup

Example dashboard JSON:

json
{
  "panels": [
    {
      "title": "Active Connections",
      "targets": [
        {
          "expr": "pg_stat_activity_count{datname='mydb',state='active'}"
        }
      ]
    },
    {
      "title": "Transaction Rate",
      "targets": [
        {
          "expr": "rate(pg_stat_database_xact_commit{datname='mydb'}[5m])"
        }
      ]
    }
  ]
}

3. pgMonitor Configuration

Example pgMonitor setup:

bash
# Install pgMonitor
git clone https://github.com/CrunchyData/pgmonitor.git
cd pgmonitor/exporter
./install-pg-exporter.sh

# Configure metrics collection
cat << EOF > /etc/pgmonitor/exporter/postgres/queries.yml
pg_replication:
  query: "SELECT * FROM pg_stat_replication"
  metrics:
    - write_lag_bytes
    - replay_lag_bytes
EOF

Query Performance Monitoring

1. Slow Query Analysis

sql
-- Create extension if not exists
CREATE EXTENSION pg_stat_statements;

-- Find slow queries
SELECT 
    substring(query, 1, 50) as short_query,
    round(total_time::numeric, 2) as total_time,
    calls,
    round(mean_time::numeric, 2) as mean_time,
    round((100 * total_time / sum(total_time::numeric) over ())::numeric, 2) as percentage
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;

2. Index Usage Monitoring

sql
-- Monitor index usage
SELECT 
    schemaname,
    tablename,
    indexname,
    idx_scan as number_of_scans,
    idx_tup_read as tuples_read,
    idx_tup_fetch as tuples_fetched
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC;

System Resource Monitoring

1. CPU Usage Monitoring

sql
-- Check CPU-intensive queries
SELECT 
    pid,
    datname,
    usename,
    query_start,
    state,
    query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY query_start;

2. Memory Usage

sql
-- Monitor shared buffer usage
SELECT 
    buffers_clean,
    buffers_backend,
    buffers_backend_fsync
FROM pg_stat_bgwriter;

-- Check memory context usage
SELECT 
    name,
    setting,
    unit,
    context
FROM pg_settings
WHERE name LIKE '%memory%' OR name LIKE '%buffer%';

Alerting Strategies

1. Connection Alerts

sql
-- Create alert function for connection threshold
CREATE OR REPLACE FUNCTION check_connection_threshold()
RETURNS trigger AS $$
BEGIN
    IF (SELECT count(*) FROM pg_stat_activity) > 
       (current_setting('max_connections')::int * 0.8) THEN
        PERFORM pg_notify(
            'connection_alert',
            'Connection threshold exceeded: ' || count(*) || ' connections'
        );
    END IF;
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

2. Replication Lag Alerts

sql
-- Monitor replication lag
SELECT 
    client_addr,
    state,
    sent_lsn,
    write_lsn,
    flush_lsn,
    replay_lsn,
    pg_wal_lsn_diff(sent_lsn, replay_lsn) as lag_bytes
FROM pg_stat_replication;

Best Practices

1. Regular Maintenance

sql
-- Monitor table bloat
WITH constants AS (
    SELECT current_setting('block_size')::numeric AS bs
)
SELECT 
    schemaname,
    tablename,
    pg_size_pretty(bloat_size) as bloat_size,
    round(bloat_ratio::numeric, 2) as bloat_ratio
FROM (
    SELECT 
        schemaname,
        tablename,
        bs*n_live_tup as actual_size,
        bs*reltuples as expected_size,
        bs*(reltuples-n_live_tup) as bloat_size,
        100.0 * (reltuples-n_live_tup)/reltuples as bloat_ratio
    FROM pg_stat_user_tables t
    JOIN pg_class c ON t.relname = c.relname
    CROSS JOIN constants
    WHERE reltuples > 0
) s
WHERE bloat_ratio > 10
ORDER BY bloat_size DESC;

2. Vacuum Monitoring

sql
-- Monitor autovacuum activity
SELECT 
    schemaname,
    relname,
    last_vacuum,
    last_autovacuum,
    vacuum_count,
    autovacuum_count
FROM pg_stat_user_tables;

3. Logging Configuration

ini
# postgresql.conf logging settings
log_min_duration_statement = 1000  # Log queries taking more than 1 second
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
log_temp_files = 0
log_autovacuum_min_duration = 0

Monitoring Automation Script

Here's a sample Python script for automated monitoring:

python
import psycopg2
import time
from datetime import datetime

def monitor_database():
    conn = psycopg2.connect("dbname=postgres user=postgres")
    cur = conn.cursor()
    
    # Collect metrics
    metrics = {
        'timestamp': datetime.now(),
        'connections': {},
        'performance': {},
        'storage': {}
    }
    
    # Connection metrics
    cur.execute("""
        SELECT count(*), state 
        FROM pg_stat_activity 
        GROUP BY state
    """)
    metrics['connections']['by_state'] = dict(cur.fetchall())
    
    # Performance metrics
    cur.execute("""
        SELECT datname, xact_commit, xact_rollback
        FROM pg_stat_database
        WHERE datname = current_database()
    """)
    metrics['performance']['transactions'] = cur.fetchone()
    
    # Storage metrics
    cur.execute("""
        SELECT pg_size_pretty(pg_database_size(current_database()))
    """)
    metrics['storage']['database_size'] = cur.fetchone()[0]
    
    return metrics

def main():
    while True:
        try:
            metrics = monitor_database()
            # Process metrics (e.g., send to monitoring system)
            print(f"Metrics collected at {metrics['timestamp']}")
            time.sleep(60)  # Collect metrics every minute
        except Exception as e:
            print(f"Error collecting metrics: {e}")
            time.sleep(5)

if __name__ == "__main__":
    main()

Conclusion

Effective PostgreSQL monitoring is essential for maintaining database health and performance. By implementing the monitoring strategies and tools discussed in this guide, you can:

  1. Proactively identify and resolve issues
  2. Optimize database performance
  3. Plan capacity effectively
  4. Ensure high availability
  5. Maintain data integrity

Remember to regularly review and adjust your monitoring setup as your database requirements evolve. The key is to find the right balance between comprehensive monitoring and system overhead.

Additional Resources

Written by

TheDBAdmin Team

KEEP LEARNING WITH THEDBADMIN

Turn this guide into a skill you can prove

Keep reading

Featured course · New batch

NextGen DBA + AI Engineer Bootcamp

Instructor-led, lab-first training for production DBAs: PostgreSQL, MongoDB, Docker, Kubernetes and AI.

  • Live labs on real execution plans
  • Backup, PITR & HA in production
  • pgvector, RAG & AI for DBAs

🛒 FROM THE SHOP

pg_auto_failover setup with two nodes

PDF · 19 pages

₹99₹4,99998% off

View product