Может ли объявление волатильности функции НЕМНОГО повредить производительности?

9

Функции Postgres объявлены с классификацией волатильности VOLATILE, STABLEилиIMMUTABLE . Известно, что проект очень строг с этими метками для встроенных функций. И не без причины. Показательный пример: индексы выражений допускают только IMMUTABLEфункции, и они должны быть действительно неизменными, чтобы избежать неверных результатов.

Пользовательские функции все еще могут быть объявлены по усмотрению владельца. Руководство советует:

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

... и добавляет обширный список вещей, которые могут пойти не так с неправильной меткой волатильности.

Тем не менее, есть случаи, когда имитация неизменности имеет смысл. Главным образом, когда вы знаете, что функция фактически неизменна в вашей области видимости. Пример:

За исключением всех возможных последствий для целостности данных , как это влияет на производительность? Можно предположить, что объявление функции IMMUTABLEможет быть полезным только для производительности . Это так?

Может ли объявление волатильности функций IMMUTABLE повредить производительности?

Давайте предположим, что нынешний Postgres 10 сузит его, но все последние версии представляют интерес.

Эрвин Брандштеттер
источник
1
Также отметим, что «по-настоящему неизменный» по индексам выражений - это настоящая лава. Это ужасный интерфейс. Мы должны быть в состоянии в FORCEлюбом случае. 100% опытных администраторов баз данных PostgreSQL лгут, чтобы обойти этот пользовательский интерфейс с помощью функций-оболочек. По крайней мере FORCE, нам не понадобятся обертки, и нам не придется лежать на объявленной волатильности.
Эван Кэрролл
1
Я предполагаю, FORCEчто предполагается, что индексы выражений принимают неизменные функции (помечая их как потенциальную точку отказа). Да, это кажется более элегантным решением, чем обертки с неизменяемыми функциями.
Эрвин Брандштеттер
Я почти ничего не знаю о PostGres, но разве волатильность не является избыточной? Что это значит? Серьезно, не ожидайте, что это будет надежно, потому что это безумие ?
Энтони
@ Энтони: я уточнил еще немного. Перейдите по ссылке на руководство для деталей.
Эрвин Брандштеттер

Ответы:

7

Да, это может повредить производительности.

Простые функции SQL могут быть «встроены» в вызывающий запрос. Цитирую Postgres Wiki :

Функции SQL (т. LANGUAGE SQLЕ.) При определенных условиях будут иметь встроенные в вызывающий запрос тела функций, а не вызываться напрямую. Это может иметь существенные преимущества в производительности, поскольку тело функции становится доступным для планировщика вызывающего запроса, который может применять такие оптимизации, как постоянное свертывание, квалифицированное нажатие и т. Д.

Жирный акцент мой.

Для обеспечения правильности существует ряд предварительных условий. Один из них :

если функция объявлена IMMUTABLE, то выражение не должно вызывать какую-либо неизменяемую функцию или оператор

Это означает, что функции SQL, использующие любые неизменяемые функции, но все еще объявленные IMMTUTABLE, исключаются из этой оптимизации. Вызванные этими связанными ответами на SO, я провел обширные тесты:

В основном, сравнивая эти два варианта простой функции SQL (сопоставление дат и integerигнорирование года, который не имеет значения для этой цели):

CREATE FUNCTION f_mmdd_tc_s(date) RETURNS int LANGUAGE sql STABLE    AS
$$SELECT to_char($1, 'MMDD')::int$$;

CREATE FUNCTION f_mmdd_tc_i(date) RETURNS int LANGUAGE sql IMMUTABLE AS
$$SELECT to_char($1, 'MMDD')::int$$;  -- cannot be inlined!

Функция Postgres to_char()есть только STABLE, нет IMMUTABLE(все ее перегруженные экземпляры - по причинам, выходящим за рамки этого ответа ). Таким образом, второй - фальшивка IMMUTABLEи оказывается в 5 раз медленнее в простом тесте:

дБ <> скрипка здесь

Этот конкретный пример можно заменить на эквивалентный:

CREATE FUNCTION f_mmdd(date) RETURNS int LANGUAGE sql IMMUTABLE AS
$$SELECT (EXTRACT(month FROM $1) * 100 + EXTRACT(day FROM $1))::int$$;

Казалось бы , дороже с двумя вызовами функций и большим количеством вычислений. Но IMMUTABLEметка верна (плюс, используемая функция быстрее и принуждение textк тому integerже дороже).

В 2 раза быстрее, чем вышеупомянутый вариант (в 10 раз быстрее, чем медленнее). Суть в том, что: используйте IMMUTABLEфункции там , где это возможно , тогда вам не нужно «обманывать» для начала.

Эрвин Брандштеттер
источник
Классные выводы! Немедленно проследите за этим: dba.stackexchange.com/q/212198/2639
Эван Кэрролл
Вы знаете, что я думаю, что я пропустил здесь, что я не знал. Это STABLEтоже встраивание. Я думал, что оптимизатор будет IMMUTABLEработать только онлайн .
Эван Кэрролл
VOLATILEточно также.
Эрвин Брандштеттер
В вики сказано, что функция объявлена ​​STABLE или IMMUTABLE. Wiki.postgresql.org/wiki/Inlining_of_SQL_functions
Эван Кэрролл,
.. в разделе "Условия наложения для табличных функций ". Не для скалярных функций. Я продемонстрировал это в скрипичном: dbfiddle.uk/...
Эрвин Brandstetter