Интересно, что производительность падает, когда объявляется простая функция SQL STRICT
.Я наткнулся на это явление, когда отвечаю на вопрос здесь .
Чтобы продемонстрировать эффект, я создаю два варианта простой функции SQL, которая упорядочивает два элемента массива в порядке возрастания.
Тестовая установка
-- temporary table with 10000 random pairs of integer
CREATE TEMP TABLE arr (i int[]);
INSERT INTO arr
SELECT ARRAY[(random() * 1000)::int, (random() * 1000)::int]
FROM generate_series(1,10000);
Функция с модификатором STRICT
:
CREATE OR REPLACE FUNCTION f_sort_array1(int[]) RETURNS int[] AS
$$
SELECT CASE WHEN $1[1] > $1[2] THEN ARRAY[$1[2], $1[1]] ELSE $1 END;
$$ LANGUAGE sql STRICT IMMUTABLE;
Функция без модификатора STRICT
(в остальном идентична):
CREATE OR REPLACE FUNCTION f_sort_array2(int[]) RETURNS int[] AS
$$
SELECT CASE WHEN $1[1] > $1[2] THEN ARRAY[$1[2], $1[1]] ELSE $1 END;
$$ LANGUAGE sql IMMUTABLE;
Результаты
Я выполнил каждое примерно 20 раз и получил лучший результат из EXPLAIN ANALYZE
.
SELECT f_sort_array1(i) FROM arr; -- Total runtime: 103 ms
SELECT f_sort_array2(i) FROM arr; -- Total runtime: 43 ms (!!!)
Это результаты с сервера v9.0.5 в Debian Squeeze.Аналогичные результаты на v8.4.Не тестировал на 9.1, сейчас нет кластера в моем распоряжении.(Может ли кто-нибудь предоставить дополнительные результаты для v9.1?)
Редактировать: В тесте с 10000 значениями NULL обе функции выполняют одинаковые в одной и той же тестовой среде: ~ 37 мс.
Я сделалнекоторые исследования и нашли интересную ошибку.Объявление функции SQL STRICT отключает встраивание функции в большинстве случаев.Подробнее об этом можно узнать в PostgreSQL Online Journal или в списке рассылки pgsql-performance или в Postgres Wiki .
Но я не являюсьвполне уверен, как это может быть объяснением.Как нельзя встраивать функцию в такой простой сценарий?Нет индекса, нет чтения диска, нет сортировки.Может быть, накладные расходы от повторного вызова функции, которые упорядочены путем встраивания функции?Вы можете это объяснить?Или я что-то упустил?
Повторное тестирование с Postgres 9.1
Тот же тест на том же оборудовании с PostgreSQL 9.1 обнаружил еще большие различия:
SELECT f_sort_array1(i) FROM arr; -- Total runtime: 107 ms
SELECT f_sort_array2(i) FROM arr; -- Total runtime: 27 ms (!!!)
Повторное тестирование с Postgres 9.6
Тот же тест на другом оборудовании с PostgreSQL 9.6.Разрыв еще больше, но:
SELECT f_sort_array1(i) FROM arr; -- Total runtime: 60 ms
SELECT f_sort_array2(i) FROM arr; -- Total runtime: 10 ms (!!!)