Como posso comparar uma consulta PostgreSQL?

34

Quero comparar uma consulta que contém uma função definida pelo usuário que escrevi para o PostgreSQL. Existem maneiras padrão de executar essa referência?

Eu sei que o tempo pode ser ativado no \timingprompt do psql, mas, idealmente, eu gostaria de ter um script que cuide de tudo automaticamente: executando a consulta algumas vezes, limpando o cache do PostgreSQL após cada execução (provavelmente reiniciando o PostgreSQL) serviço) e exibindo o tempo médio de execução (e a memória usada é uma vantagem).

Franck Dernoncourt
fonte
3
Confira pgbench; você pode executá-lo com scripts personalizados para fazer o que quiser. Com um script de shell de invólucro para parar e reiniciar a Pg e soltar o cache do disco do SO, você tem mais do que precisa.
Craig Ringer
Não é uma duplicata do dba.stackexchange.com/questions/3148/… .
Jon of All Trades

Respostas:

29

A ferramenta amplamente usada é o comando SQL EXPLAIN ANALYZE, possivelmente com mais opções para obter mais detalhes na resposta. Isso gera o plano de consulta com as estimativas do planejador mais os tempos de execução reais.

Por que você deseja limpar o cache? O caso de uso geralmente mais provável é que o cache seja preenchido. Se você ainda deseja seguir esse caminho, aqui está uma resposta relacionada ao SO .

Não redefinindo o cache, aqui estão duas maneiras simples de testar com muitas iterações:

UDF simples

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

Ou com entrada aleatória - números aleatórios entre 0 e 5000 no exemplo:

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

Ou com uma mesa da vida real:

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

Funções / consultas mais complexas

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

Ligar:

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

Cuidado : a consulta é realmente executada!
Cuidado : Não é adequado para uso público. Possível injeção de SQL.

Novamente, você pode usar parâmetros aleatórios, se necessário. Possivelmente com a USINGcláusula de EXECUTE.

Erwin Brandstetter
fonte