Функция выполняется быстрее без модификатора STRICT? - PullRequest
5 голосов
/ 10 декабря 2011

Интересно, что производительность падает, когда объявляется простая функция 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 (!!!)

1 Ответ

3 голосов
/ 10 декабря 2011

Может быть, накладные расходы от повторного вызова функции, которые упорядочены путем встраивания функции?

Это то, что я догадываюсь.У вас там очень простое выражение.Фактический вызов функции, вероятно, включает в себя настройку стека, передачу параметров и т. Д.

Приведенный ниже тест дает время выполнения 5 мс для встроенного и 50 мс для строгого.

...