pg_stat_statements to wbudowane rozszerzenie PostgreSQL, które pozwala śledzić, jakie zapytania faktycznie dzieją się w bazie i jak się zachowują. To taki cichy, ale czujny pomocnik, który zapisuje każdy krok: jakie zapytania SQL były wykonywane, ile czasu zajęły, jak często były uruchamiane i jak bardzo obciążały system.
Po co to wszystko? Po pierwsze, żeby znaleźć problematyczne zapytania. Czasem baza zamula nie przez jednego złoczyńcę, ale przez dziesiątki takich samych ciężkich zapytań, które odpalają się zbyt często. Po drugie, statystyki pomagają zobaczyć, które zapytania zjadają zasoby — procesor, pamięć, dysk. Możesz też sprawdzić, czy indeksy działają tak, jak planowałeś: może gdzieś w ogóle się nie używają, a gdzie indziej — wręcz przeciwnie, brakuje ich.
pg_stat_statements pozwala nie zgadywać, tylko widzieć realne liczby — i na ich podstawie wyciągać wnioski oraz optymalizować.
Jak znaleźć wolne zapytania?
Teraz zaczyna się najciekawsze! Używając tabeli pg_stat_statements, możemy szukać zapytań, które wykonują się długo albo mocno obciążają serwer.
Główna idea:
Każdy wiersz w tabeli pg_stat_statements to statystyka dla jednego zapytania. Zapytania są grupowane po ich tekście (pole query), a dla każdego z nich liczone są takie metryki:
total_time— całkowity czas wykonania zapytania, w milisekundach.calls— liczba wykonań zapytania.mean_time— średni czas wykonania zapytania (total_time / calls).rows— liczba wierszy, które zwróciło zapytanie.
Przykład prostego analizy
Spróbujmy znaleźć najwolniejsze zapytania według średniego czasu wykonania:
SELECT
query,
mean_time,
calls,
rows
FROM
pg_stat_statements
ORDER BY
mean_time DESC
LIMIT 5;
To zapytanie pokaże TOP-5 zapytań, które wykonują się najdłużej. Zwróć uwagę na pole mean_time: jeśli tam wartości w milisekundach przekraczają 500-1000, to sygnał, że trzeba je zoptymalizować.
Przykład analizy wolnych zapytań
Przeanalizujmy przykład:
Oto wynik wykonania poprzedniego zapytania:
| query | mean_time | calls | rows |
|---|---|---|---|
| SELECT * FROM orders WHERE status = 'nowy'; | 1234.56 | 10 | 10000 |
| SELECT * FROM products | 755.12 | 5000 | 100 |
| SELECT * FROM customers WHERE id = $1 | 543.21 | 1000 | 1 |
Co widzimy?
Zapytanie do tabeli orders: wykonuje się bardzo rzadko (tylko 10 wywołań), ale za każdym razem ciągnie ogromne 10 tysięcy wierszy. Pewnie tabela jest bardzo duża i zapytanie nie używa indeksów.
Zapytanie do tabeli products: wywoływane miliony razy, może w pętli w aplikacji. Każde pobranie zwraca tylko 100 wierszy, ale przez częstotliwość to zapytanie też może być problematyczne.
Zapytanie do tabeli customers: wykonuje się szybko (543 ms), ale jest odpalane zbyt często.
Optymalizacja wolnych zapytań
Teraz, gdy znaleźliśmy problematyczne zapytania, trzeba zobaczyć ich plan wykonania za pomocą EXPLAIN ANALYZE. Na przykład dla zapytania do tabeli orders:
EXPLAIN ANALYZE
SELECT * FROM orders WHERE status = 'nowy';
Co możemy zobaczyć?
Seq Scan: jeśli zapytanie używa sekwencyjnego skanowania, trzeba dodać indeks:
CREATE INDEX idx_orders_status ON orders (status);
Problemy z filtrowaniem: jeśli zapytanie ciągnie za dużo wierszy, przemyśl sam tekst zapytania. Może trzeba dodać dodatkowe warunki albo ograniczyć wyniki:
SELECT * FROM orders WHERE status = 'nowy' LIMIT 100;
Wyświetlanie statystyk czasu wykonania
Czasem problematyczne zapytania nie są takie oczywiste. Na przykład zapytania, które często wywołują funkcje albo podzapytania. W takich przypadkach warto patrzeć na kolumnę total_time:
SELECT
query,
total_time,
calls,
mean_time
FROM
pg_stat_statements
ORDER BY
total_time DESC
LIMIT 10;
To zapytanie pokaże najbardziej "kosztowne" zapytania według sumarycznego czasu wykonania.
Optymalizacja indeksowania
Często wolne zapytania są związane z brakiem potrzebnych indeksów. Użyj pg_stat_statements, żeby zobaczyć, które zapytania nie używają indeksów. Jeśli widzisz dużo zapytań z tymi samymi filtrami (np. po polu status), ale są bardzo wolne, dodaj odpowiedni indeks:
CREATE INDEX idx_orders_status ON orders (status);
Po tym sprawdź wydajność zapytania jeszcze raz z EXPLAIN ANALYZE.
Korzystając z pg_stat_statements, możesz skutecznie śledzić wydajność zapytań, znajdować "wąskie gardła" i poprawiać wydajność swojej bazy danych. Pamiętaj, że im szybciej zaczniesz analizować zapytania, tym łatwiej będzie zoptymalizować działanie całego systemu.
GO TO FULL VERSION