PostgreSQL: неизменный, изменчивый, стабильный

11

Я не уверен относительно истинного значения в определениях для функций IMMUTABLE, VOLATILE и STABLE.

Я прочитал документацию, в частности, определения каждого.

IMMUTABLE указывает, что функция не может изменять базу данных и всегда возвращает один и тот же результат, если даны одинаковые значения аргумента ; то есть он не выполняет поиск в базе данных или иным образом не использует информацию, непосредственно не представленную в его списке аргументов. Если указан этот параметр, любой вызов функции с полностью константными аргументами может быть немедленно заменен значением функции.

STABLE указывает, что функция не может изменить базу данных и что при сканировании одной таблицы она будет последовательно возвращать один и тот же результат для тех же значений аргумента , но что ее результат может изменяться в операторах SQL. Это подходящий выбор для функций, результаты которых зависят от поиска в базе данных, переменных параметров (таких как текущий часовой пояс) и т. Д. (Это не подходит для триггеров AFTER, которые хотят запрашивать строки, измененные текущей командой.) Также обратите внимание, что Семейство функций current_timestamp квалифицируется как стабильное, поскольку их значения не изменяются в транзакции.

VOLATILE указывает, что значение функции может измениться даже в течение одного сканирования таблицы, поэтому никакие оптимизации не могут быть выполнены. В этом смысле относительно немного функций базы данных являются изменчивыми; некоторые примеры: random (), currval (), timeofday (). Но обратите внимание, что любая функция, имеющая побочные эффекты, должна быть классифицирована как изменчивая, даже если ее результат вполне предсказуем, чтобы не допустить оптимизации вызовов; Примером является setval ().

У меня возникает путаница с условием IMMUTABLE и STABLE, что функция ВСЕГДА или ПОСТОЯННО возвращает один и тот же результат при одинаковых аргументах.

Определение IMMUTABLE гласит, что функция не выполняет поиск в базе данных или иным образом использует информацию, непосредственно не представленную в ее списке аргументов. Итак, для меня это означает, что такие функции используются для манипулирования данными, предоставленными клиентом, и не должны иметь операторов SELECT ... хотя это звучит немного странно для меня.

С STABLE определение похоже на то, что оно должно последовательно возвращать один и тот же результат. Поэтому для меня это означает, что каждый раз, когда функция вызывается с одинаковыми аргументами, она должна возвращать одинаковые результаты (одинаковые точные строки, каждый раз).

Итак, для меня ... это означает, что любая функция, которая выполняет SELECT для таблицы или таблиц, которые могут быть обновлены, должна быть только изменчивой.

Но, опять же ... это не звучит правильно для меня.

Возвращаясь к моему сценарию использования, я пишу функции, которые выполняют операторы SELECT с несколькими таблицами JOIN, к которым постоянно добавляются таблицы, поэтому ожидается, что вызовы функций будут возвращать разные результаты при каждом вызове, даже с одинаковыми аргументами ,

Значит ли это, что мои функции должны быть ВОЛАТНЫМИ? Даже если в документации указано, что относительно немного функций базы данных в этом смысле изменчивы ?

Спасибо!

Brooks
источник

Ответы:

15

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

STABLEМожно использовать любые входные данные, которые сами по себе STABLE: другие STABLEили IMMUTABLEфункции, а также SELECTзапросы таблиц. Безопасно запрашивать таблицы, потому что представление функции этих таблиц не изменится в текущем снимке запроса. Вы можете получить доступ к значениям GUC ( current_setting(...)), если вы знаете, что они не будут назначены в текущем операторе.

VOLATILE функции - это все, что не соответствует вышесказанному

  • Что-нибудь с побочными эффектами
  • Все, что пишет
  • Все, что запрашивает внешние данные, не управляемые снимком PostgreSQL
  • ...

В общем, просто оставьте все, VOLATILEесли у вас нет веских причин не делать этого.

Основная причина использования IMMUTABLE- при написании функций, которые должны использоваться как часть выражений индекса.

Крейг Рингер
источник
1
«они не могут получить доступ к таблицам». Справедливости ради, они могут и они делают. Я думаю, что более общим правилом является то, что таблицы не должны значимо мутировать без перезапуска базы данных.
Эван Кэрролл,
Если STABLE разрешает доступ к таблице, есть ли оптимизация выше / выше VOLATILE ...?
Брукс
Не помню, с головы до головы, придется проверить документы / код.
Крейг Рингер
4

Для STABLE, часть, которую нужно выделить жирным шрифтом, это «результат может измениться в операторах SQL»

Неизменные вещи не должны меняться никогда. Даже если вы перезагрузите ваш сервер базы данных, запустите yum update(но, конечно, могут быть ошибки!), Изменить конфигурацию (как datestyle, timezone, default_text_search_config, extra_float_digitsи т.д.), или заменить серверное оборудование полностью (из той же архитектуры, что и старое оборудование, так бинарные файлы все еще совместимы).

Описанные вами функции звучат так, как будто они STABLE, потому что в пределах одного оператора SQL они будут выполнять свои запросы, используя тот же моментальный снимок, что и внешний запрос, и поэтому любые параллельные изменения, внесенные вами в эти другие таблицы, не будут видны. Теперь, если ваши функции открыли новое соединение с сервером и запустили свои запросы в этом независимом соединении, это сделало бы функцию энергозависимой, потому что они использовали бы разные снимки.

jjanes
источник
Я полагаю, что понимаю предварительные условия для IMMUTABLE (ничего не может измениться ... когда-либо, между запросами, соединениями, перезагрузками, уничтожением и реконструкцией планет, ДАЖЕ ЕСЛИ база данных изменена) и VOLATILE (функция выходит за пределы контекста в который это называлось). Это верно? Итак, тогда кажется STABLE просто означает, что функция не изменяет базу данных и не обращается к базе данных вне ее контекста? Определение STABLE выглядит так, как будто оно намного сложнее, чем на самом деле должно быть ... Или я что-то упускаю?
Брукс,
PostgreSQL на самом деле имеет некоторые проблемы IMMUTABLEи сопоставления. Он полагает, что glibc(или, в более новой версии Pg, iconv) не изменит определения параметров сортировки. На самом деле они это делают и не дают возможности обнаружить такие изменения. Это может привести к повреждению индекса без вывода сообщений :(. Это в основном проблема при репликации между различными версиями ОС и т. Д.
Крейг Рингер