Вопрос новичка:
У меня есть дорогая функция f(x, y)
на двух столбцах х и у в моей таблице базы данных.
Я хочу выполнить запрос, который дает мне результат функции в виде столбца и накладывает на него ограничение, что-то вроде
SELECT *, f(x, y) AS func FROM table_name WHERE func < 10;
Однако это не работает, поэтому мне придется написать что-то вроде
SELECT *, f(x, y) AS func FROM table_name WHERE f(x, y) < 10;
Будет ли это запускать дорогую функцию дважды? Какой лучший способ сделать это?
postgresql
postgresql-9.4
Джек Блэк
источник
источник
STABLE
/IMMUTABLE
илиVOLATILE
?Ответы:
Давайте создадим функцию с побочным эффектом, чтобы мы могли видеть, сколько раз она выполняется:
А затем назовите это так, как вы делаете:
Как видите, функция вызывается как минимум один раз (из
WHERE
условия), а когда условие истинно, еще раз выдает результат.Чтобы избежать второго выполнения, вы можете сделать то, что предлагает Эдгар, а именно - обернуть запрос и отфильтровать результирующий набор:
Чтобы дополнительно проверить, как это работает, можно перейти
pg_stat_user_functions
и проверитьcalls
там (даноtrack_functions
установлено «все»).Давайте попробуем что-то, что не имеет побочных эффектов:
simple()
на самом деле слишком прост, поэтому может быть встроен , поэтому он не отображается в представлении. Давайте сделаем это неотъемлемым:Как это выглядит, картина одинакова с побочными эффектами или без них.
Изменение
other_one()
кIMMUTABLE
изменению поведения (возможно, на удивление) в худшую сторону, так как оно будет вызываться 13 раз в обоих запросах.источник
Попробуйте позвонить еще раз:
источник