¿Cómo puedo comparar una consulta PostgreSQL?

34

Quiero comparar una consulta que contiene una función definida por el usuario que he escrito para PostgreSQL. ¿Hay alguna forma estándar de ejecutar ese punto de referencia?

Sé que el tiempo se puede activar \timingen el indicador de psql, pero idealmente me gustaría tener un script que se encargue de todo automáticamente: ejecutar la consulta varias veces, borrar el caché de PostgreSQL después de cada ejecución (probablemente reiniciando el PostgreSQL servicio), y generar el tiempo de ejecución promedio (y la memoria utilizada es una ventaja).

Franck Dernoncourt
fuente
3
Echa un vistazo pgbench; puedes ejecutarlo con scripts personalizados para hacer algo de lo que quieras. Con un script de shell envoltorio para detener y reiniciar Pg y soltar el caché de disco del sistema operativo, tiene la mayor parte de lo que necesita.
Craig Ringer
No es un duplicado de dba.stackexchange.com/questions/3148/… .
Jon of All Trades

Respuestas:

29

La herramienta más utilizada es el comando SQL EXPLAIN ANALYZE, posiblemente con más opciones para obtener más detalles en la respuesta. Eso genera el plan de consulta con las estimaciones del planificador más los tiempos de ejecución reales.

¿Por qué querrías borrar el caché? El caso de uso generalmente más probable es que el caché está poblado. Si aún desea seguir esa ruta, aquí hay una respuesta relacionada con SO .

Sin restablecer el caché, aquí hay dos formas simples de probar con muchas iteraciones:

UDF simple

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

O con entrada aleatoria: números aleatorios entre 0 y 5000 en el ejemplo:

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

O con una mesa de la vida real:

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

Funciones / consultas más complejas

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

Llamada:

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

Cuidado : ¡la consulta se ejecuta realmente!
Cuidado : no apto para uso público. Posible inyección de SQL.

Nuevamente, puede usar parámetros aleatorios si es necesario. Posiblemente con la USINGcláusula de EXECUTE.

Erwin Brandstetter
fuente