Завершающим этапом мы настроили полноценный мониторинг, чтобы команда клиента могла отслеживать состояние базы данных в реальном времени.
-- Топ-20 самых тяжёлых запросов (требуется pg_stat_statements)
SELECT
queryid,
LEFT(query, 100) AS query_preview,
calls,
ROUND(total_exec_time::numeric / 1000, 2) AS total_time_sec,
ROUND(mean_exec_time::numeric, 2) AS mean_time_ms,
rows,
ROUND(shared_blks_hit::numeric / NULLIF(shared_blks_hit + shared_blks_read, 0) * 100, 2) AS cache_hit_pct
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 20;
-- Текущие активные запросы
SELECT
pid,
now() - pg_stat_activity.query_start AS duration,
usename,
datname,
state,
LEFT(query, 200) AS query
FROM pg_stat_activity
WHERE state != 'idle'
AND pid != pg_backend_pid()
ORDER BY duration DESC;
-- Блокировки
SELECT
blocked.pid AS blocked_pid,
blocked.usename AS blocked_user,
blocking.pid AS blocking_pid,
blocking.usename AS blocking_user,
LEFT(blocked.query, 100) AS blocked_query,
LEFT(blocking.query, 100) AS blocking_query
FROM pg_stat_activity AS blocked
JOIN pg_locks AS bl ON bl.pid = blocked.pid
JOIN pg_locks AS kl ON kl.locktype = bl.locktype
AND kl.database IS NOT DISTINCT FROM bl.database
AND kl.relation IS NOT DISTINCT FROM bl.relation
AND kl.page IS NOT DISTINCT FROM bl.page
AND kl.tuple IS NOT DISTINCT FROM bl.tuple
AND kl.pid != bl.pid
AND NOT kl.granted
JOIN pg_stat_activity AS blocking ON blocking.pid = kl.pid
WHERE NOT bl.granted;
-- Размеры баз данных
SELECT
datname,
pg_size_pretty(pg_database_size(datname)) AS size
FROM pg_database
ORDER BY pg_database_size(datname) DESC;
# Устанавливаем postgres_exporter
wget https://github.com/prometheus-community/postgres_exporter/releases/latest/download/postgres_exporter-linux-amd64.tar.gz
tar xzf postgres_exporter-linux-amd64.tar.gz
sudo mv postgres_exporter /usr/local/bin/
# Создаём пользователя мониторинга
sudo -u postgres psql -c "
CREATE USER monitoring WITH PASSWORD 'MonitorP@ss!';
GRANT pg_monitor TO monitoring;"
# Создаём systemd unit
sudo cat > /etc/systemd/system/postgres-exporter.service <
Мы импортировали готовый дашборд Grafana ID 9628 (PostgreSQL Database) для визуализации метрик: количество подключений, кеш-хит, TPS, размер WAL, задержка репликации и bloat таблиц.