Jak mogę przeprowadzić analizę porównawczą zapytania PostgreSQL?

34

Chcę przeprowadzić analizę porównawczą zapytania zawierającego zdefiniowaną przez użytkownika funkcję, którą napisałem dla PostgreSQL. Czy są jakieś standardowe sposoby przeprowadzenia takiego testu porównawczego?

Wiem, że czas można włączyć \timingw wierszu polecenia psql, ale idealnie chciałbym mieć skrypt, który zajmie się wszystkim automatycznie: uruchamianie zapytania kilka razy, czyszczenie pamięci podręcznej PostgreSQL po każdym uruchomieniu (prawdopodobnie przez ponowne uruchomienie PostgreSQL's usługi) i wyprowadzenie średniego czasu działania (a wykorzystana pamięć to plus).

Franck Dernoncourt
źródło
3
Sprawdź pgbench; możesz uruchomić go z niestandardowymi skryptami, aby zrobić to, co chcesz. Ze skryptem otoki powłoki, aby zatrzymać i ponownie uruchomić Pg oraz upuścić pamięć podręczną dysku systemu operacyjnego, masz większość tego, czego potrzebujesz.
Craig Ringer
Niezupełnie duplikat dba.stackexchange.com/questions/3148/… .
Jon of All Trades

Odpowiedzi:

29

Powszechnie używanym narzędziem jest polecenie SQL EXPLAIN ANALYZE, prawdopodobnie z większą liczbą opcji pozwalających uzyskać więcej szczegółów w odpowiedzi. To generuje plan zapytań wraz z szacunkami planisty oraz faktycznymi czasami wykonania.

Dlaczego chcesz wyczyścić pamięć podręczną? Ogólnie bardziej prawdopodobnym przypadkiem użycia jest zapełnienie pamięci podręcznej. Jeśli nadal chcesz wybrać tę trasę, oto pokrewna odpowiedź na temat SO .

Nie resetując pamięci podręcznej, oto dwa proste sposoby testowania z wieloma iteracjami:

Prosty UDF

EXPLAIN ANALYZE
SELECT f_myfunc(g) FROM generate_series (1,1000) AS t(g);

Lub z losowym wprowadzaniem - liczby losowe od 0 do 5000 w przykładzie:

EXPLAIN ANALYZE
SELECT f_myfunc((random()*5000)::int) FROM generate_series (1,1000) AS t(g);

Lub z prawdziwym stołem:

EXPLAIN ANALYZE
SELECT f_myfunc(my_column) FROM my_tbl;   -- LIMIT n

Bardziej złożone funkcje / zapytania

CREATE FUNCTION f_test(ct int, sql text) RETURNS void AS
$func$
DECLARE
   i int;
BEGIN

FOR i IN 1 .. $1 LOOP
    EXECUTE sql;  -- not safe against SQLi!
END LOOP;

END
$func$ LANGUAGE plpgsql

Połączenie:

EXPLAIN ANALYZE
SELECT f_test(100, $x$SELECT * from MADLIB.gp('mock3', '{x1, x2, x3}', '{y1}', 100,20, 3)$x$

Ostrożnie : zapytanie jest faktycznie wykonywane!
Ostrożnie : nie nadaje się do użytku publicznego. Możliwy zastrzyk SQL.

Ponownie w razie potrzeby można użyć losowych parametrów. Być może z USINGklauzulą EXECUTE.

Erwin Brandstetter
źródło