Wie kann ich eine PostgreSQL-Abfrage bewerten?

34

Ich möchte eine Abfrage mit einer benutzerdefinierten Funktion vergleichen, die ich für PostgreSQL geschrieben habe. Gibt es Standardmethoden, um einen solchen Benchmark durchzuführen?

Ich weiß, dass das Timing mit \timingder psql-Eingabeaufforderung aktiviert werden kann, aber im Idealfall hätte ich gerne ein Skript, das alles automatisch erledigt: die Abfrage ein paar Mal ausführen und den PostgreSQL-Cache nach jedem Lauf löschen (wahrscheinlich durch Neustart der PostgreSQLs) Service) und die Ausgabe der durchschnittlichen Laufzeit (und des verwendeten Speichers ist ein Plus).

Franck Dernoncourt
quelle
3
Check out pgbench; Sie können es mit benutzerdefinierten Skripten ausführen, um einige der gewünschten Aktionen auszuführen. Mit einem Wrapper-Shell-Skript zum Stoppen und Neustarten von Pg und zum Löschen des Betriebssystem-Festplatten-Cache haben Sie das meiste, was Sie brauchen.
Craig Ringer
Nicht ganz ein Duplikat von dba.stackexchange.com/questions/3148/… .
Jon of All Trades

Antworten:

29

Das am häufigsten verwendete Tool ist der SQL-Befehl EXPLAIN ANALYZE, möglicherweise mit mehr Optionen für weitere Details in der Antwort. Das gibt den Abfrageplan mit den Planerschätzungen und den tatsächlichen Ausführungszeiten aus.

Warum soll der Cache geleert werden? Der allgemein wahrscheinlichere Anwendungsfall ist, dass der Cache gefüllt ist. Wenn Sie diesen Weg immer noch einschlagen möchten, finden Sie hier eine Antwort auf SO .

Wenn Sie den Cache nicht zurücksetzen, haben Sie zwei einfache Möglichkeiten, ihn mit vielen Iterationen zu testen:

Einfaches UDF

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

Oder mit Zufallseingabe - Zufallszahlen zwischen 0 und 5000 im Beispiel:

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

Oder mit einem echten Tisch:

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

Komplexere Funktionen / Abfragen

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

Anruf:

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

Achtung : Die Abfrage wird tatsächlich ausgeführt!
Achtung : Nicht für den öffentlichen Gebrauch geeignet. Mögliche SQL-Injection.

Bei Bedarf können Sie auch hier zufällige Parameter verwenden. Möglicherweise mit der USINGKlausel von EXECUTE.

Erwin Brandstetter
quelle