Как ключевые слова IMMUTABLE, STABLE и VOLATILE влияют на поведение функции?

Мы написали функцию get_timestamp() определенную как

 CREATE OR REPLACE FUNCTION get_timestamp() RETURNS integer AS $$ SELECT (FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 10) - 13885344000)::int; $$ LANGUAGE SQL; 

Это использовалось для INSERT и UPDATE для ввода или редактирования значения в созданном и измененном поле в записи базы данных. Однако при добавлении или обновлении записей мы обнаружили, что оно возвращало одно и то же значение.

При проверке функции в pgAdmin III мы отметили, что при запуске SQL для построения функции ключевое слово IMMUTABLE было введено после оператора SQL LANGUAGE. В документации указано, что значением по умолчанию является VOLATILE (если ни одно из них не появляется, VOLATILE является предположением по умолчанию), поэтому я не уверен, почему IMTUTABLE был введен, однако, изменив это, STABLE решил проблему повторных значений.

ПРИМЕЧАНИЕ. Как указано в принятом ответе, IMMUTABLE никогда не добавляется к функции через pgAdmin или Postgres и должен быть добавлен во время разработки.

Я предполагаю, что происходит то, что эта функция была оценена, и результат был кэширован для оптимизации, поскольку он был отмечен IMMUTABLE, указывающий движку Postgres, что возвращаемое значение не должно изменяться с учетом того же (пустого) списка параметров. Однако, когда он не используется в триггере, когда он используется непосредственно в инструкции INSERT, функция возвращает четное значение FIVE раз, а затем возвращает то же самое значение с этого момента. Это связано с некоторым алгоритмом оптимизации, который говорит что-то вроде «Если функция IMMUTABLE используется более 5 раз в сеансе, кешируйте результат для будущих вызовов»?

Любые разъяснения относительно того, как эти ключевые слова должны использоваться в функциях Postgres, будут оценены. Является ли STABLE правильной опцией для нас, учитывая, что мы используем эту функцию в триггерах, или есть что-то большее, чтобы рассмотреть, например, документы говорят:

(Это не подходит для триггеров AFTER, которые хотят запросить строки, измененные текущей командой.)

Но я не совсем понимаю, почему.

One Solution collect form web for “Как ключевые слова IMMUTABLE, STABLE и VOLATILE влияют на поведение функции?”

Ключевое слово IMMUTABLE никогда не добавляется автоматически pgAdmin или Postgres. Кто-то создал или заменил функцию.

Правильная функция волатильности (чтение руководства) для данной функции – VOLATILE , а не STABLE – или не имеет смысла использовать clock_timestamp() который является VOLATILE а не now() или CURRENT_TIMESTAMP , которые определены STABLE : те вернуть одну и ту же метку времени в пределах одной транзакции, в соответствии с документацией :

clock_timestamp() возвращает текущее текущее время, и поэтому его значение изменяется даже в пределах одной команды SQL.

В руководстве указано, что волатильность функции STABLE

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

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

И вы спрашиваете:

У вас есть идея, почему функция вернулась правильно пять раз, прежде чем приклеивать пятое значение при установке IMMUTABLE ?

Цитирование Вики- страницы Postgres :

С 9.2 планировщик будет использовать конкретные планы относительно отправленных параметров (запрос будет запланирован при выполнении), за исключением случаев, когда запрос выполняется несколько раз, и планировщик решает, что общий план не слишком дороже, чем конкретные планы ,

Смелый акцент мой. Кажется, не имеет смысла для функции IMMUTABLE (тоже не наносит вреда), но, возможно, использование функции VOLATILE внутри все еще вызывает первоначальное перепланирование. (Последний бит – это только мои предположения.)
Больше объяснений здесь:

  • Производительность хранимых процедур PostgreSQL

В стороне

trunc() немного быстрее, чем floor() и делает то же самое здесь, поскольку положительные числа гарантированы:

 SELECT (trunc(EXTRACT(EPOCH FROM clock_timestamp()) * 10) - 13885344000)::int 
  • Когда функция слишком длинная?
  • Перейти к определению функции в vim
  • Есть ли способ использовать два оператора «...» в функции из R?
  • Встроенная функция связи
  • Функция триггера jquery, когда элемент находится в viewport
  • Почему C ++ не поддерживает функции, возвращающие массивы?
  • «Срок службы» строкового литерала в C
  • Функция возвращает None без оператора return
  • В MATLAB, могу ли я иметь скрипт и определение функции в том же файле?
  • Почему std :: function не равнозначно сопоставимо?
  • Функция Excel для создания SQL-подобных запросов в данных рабочего листа?
  • Давайте будем гением компьютера.