Как я могу сравнить запрос PostgreSQL?

34

Я хочу сравнить запрос, содержащий пользовательскую функцию, которую я написал для PostgreSQL. Существуют ли стандартные способы запуска такого теста?

Я знаю, что синхронизацию можно включить с \timingпомощью приглашения psql, но в идеале я хотел бы иметь скрипт, который обо всем позаботится автоматически: несколько раз выполнять запрос, очищать кеш PostgreSQL после каждого запуска (возможно, перезапуская PostgreSQL службы), и выводит среднее время работы (и используемая память является плюсом).

Франк Дернонкур
источник
3
Проверить pgbench; Вы можете запустить его с помощью пользовательских сценариев, чтобы сделать то, что вы хотите. С помощью сценария оболочки-оболочки для остановки и перезапуска Pg, а также для удаления дискового кэша ОС у вас есть большая часть того, что вам нужно.
Крейг Рингер
Не совсем дубликат dba.stackexchange.com/questions/3148/… .
Джон на все руки

Ответы:

29

Широко используемым инструментом является команда SQL EXPLAIN ANALYZE, возможно, с большим количеством опций для более подробной информации в ответе. Это выводит план запроса с оценками планировщика плюс фактическое время выполнения.

Почему вы хотите очистить кеш? Обычно более вероятный вариант использования - заполнение кэша. Если вы все еще хотите пойти по этому пути, вот соответствующий ответ на SO .

Не сбрасывая кеш, вот два простых способа тестирования с множеством итераций:

Простой UDF

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

Или со случайным вводом - случайные числа от 0 до 5000 в примере:

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

Или с таблицей из реальной жизни:

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

Более сложные функции / запросы

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

Вызов:

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

Осторожно : запрос фактически выполнен!
Осторожно : не подходит для публичного использования. Возможно внедрение SQL.

Опять же, вы можете использовать случайные параметры, если это необходимо. Возможно с USINGпунктом EXECUTE.

Эрвин Брандштеттер
источник