pg_stat_statements — це вбудоване розширення PostgreSQL, яке дозволяє слідкувати за тим, які запити насправді відбуваються в базі даних і як вони себе поводять. По суті, це такий тихий, але уважний помічник, який фіксує кожен крок: які SQL-запити виконувались, скільки часу вони зайняли, як часто запускались і наскільки навантажували систему.
Навіщо це потрібно? По-перше, щоб знаходити проблемні запити. Іноді база гальмує не через одного лиходія, а через десяток однакових важких запитів, які виконуються занадто часто. По-друге, статистика допомагає побачити, які саме запити з’їдають ресурси — процесор, пам’ять, диск. А ще ти можеш зрозуміти, чи працюють індекси так, як ти планував: може, десь вони взагалі не використовуються, а десь — навпаки, їх не вистачає.
pg_stat_statements дозволяє не гадати, а бачити реальні цифри — і на їх основі робити висновки та оптимізації.
Як знайти повільні запити?
Тепер починається найцікавіше! Використовуючи таблицю pg_stat_statements, ми можемо шукати запити, які виконуються довго або сильно навантажують сервер.
Основна ідея:
Кожен рядок у таблиці pg_stat_statements представляє статистику по одному запиту. Запити групуються за їх текстом (власне, поле query), і для кожного з них підраховуються такі метрики:
total_time— загальний час виконання запиту, у мілісекундах.calls— кількість виконань запиту.mean_time— середній час виконання запиту (total_time / calls).rows— кількість рядків, які повертав запит.
Приклад простого аналізу
Спробуємо знайти найповільніші запити за середнім часом виконання:
SELECT
query,
mean_time,
calls,
rows
FROM
pg_stat_statements
ORDER BY
mean_time DESC
LIMIT 5;
Цей запит покаже ТОП-5 запитів, які виконуються найдовше. Зверни увагу на поле mean_time: якщо там значення у мілісекундах перевищують 500-1000, це сигнал, що запити треба оптимізувати.
Приклад аналізу повільних запитів
Давай розглянемо приклад:
Ось результат виконання попереднього запиту:
| query | mean_time | calls | rows |
|---|---|---|---|
| SELECT * FROM orders WHERE status = 'new'; | 1234.56 | 10 | 10000 |
| SELECT * FROM products | 755.12 | 5000 | 100 |
| SELECT * FROM customers WHERE id = $1 | 543.21 | 1000 | 1 |
Що ми бачимо?
Запит до таблиці orders: виконується дуже рідко (всього 10 викликів), але кожного разу тягне величезні 10 тисяч рядків. Мабуть, таблиця дуже велика, і запит не використовує індекси.
Запит до таблиці products: викликається мільйони разів, можливо, у циклі в додатку. Кожна вибірка повертає всього 100 рядків, але через частоту цей запит теж може бути проблемою.
Запит до таблиці customers: виконується швидко (543 мс), але викликається занадто часто.
Оптимізація повільних запитів
Тепер, коли ми знайшли проблемні запити, треба подивитись їх план виконання за допомогою EXPLAIN ANALYZE. Наприклад, для запиту до таблиці orders:
EXPLAIN ANALYZE
SELECT * FROM orders WHERE status = 'new';
Що ми можемо побачити?
Seq Scan: якщо запит використовує послідовне сканування, треба додати індекс:
CREATE INDEX idx_orders_status ON orders (status);
Проблеми з фільтрацією: якщо запит тягне занадто багато рядків, переглянь сам текст запиту. Можливо, треба додати додаткові умови або обмежити результати:
SELECT * FROM orders WHERE status = 'new' LIMIT 100;
Вивід статистики за часом виконання
Іноді проблемні запити можуть бути не такими очевидними. Наприклад, запити, які часто викликають функції або підзапити. У таких випадках зручно дивитись стовпець total_time:
SELECT
query,
total_time,
calls,
mean_time
FROM
pg_stat_statements
ORDER BY
total_time DESC
LIMIT 10;
Цей запит покаже най"дорогіші" запити за сумарним часом виконання.
Оптимізація індексації
Часто повільні запити пов’язані з відсутністю необхідних індексів. Використовуй pg_stat_statements, щоб зрозуміти, які запити не використовують індекси. Якщо ти бачиш багато запитів з однаковими фільтрами (наприклад, по полю status), але вони дуже повільні, додай відповідний індекс:
CREATE INDEX idx_orders_status ON orders (status);
Після цього перевір продуктивність запиту знову з EXPLAIN ANALYZE.
Використовуючи pg_stat_statements, ти можеш ефективно слідкувати за продуктивністю запитів, знаходити "вузькі місця" і покращувати продуктивність своєї бази даних. Пам’ятай, що чим раніше ти почнеш аналізувати запити, тим простіше буде оптимізувати роботу всієї системи.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ