202
Функции
при создании функции движок базы данных компилирует ее и сохраняется
в скомпилированном виде. Функции не только хранятся в виде исходного
кода, но и, в отличие от других СУБД, они интерпретируются, а не компили-
руются.
Интерпретатор PL/pgSQL разбирает исходный текст
функции и создает
(внутреннее) дерево инструкций при первом вызове функции в каждом сеан-
се. Даже в этом случае отдельные выражения SQL и команды, используемые
в функции, не транслируются тотчас же. Только когда выполнение доходит
до определенной команды, она анализируется и для нее создается
подго-
товленный
оператор
. Он будет использован повторно, если та же функция
будет выполнена снова в том же сеансе. Одно из
следствий этого состоит
в том, что если ваша функция содержит условия (например, инструкции
IF
THEN
ELSE
или
CASE
), вы можете не обнаружить даже синтаксическую ошибку
в своем коде, если не наткнулись на нее во время выполнения. Мы видели,
как такие неприятные открытия совершались уже после того, как функция
перешла в промышленное окружение. Подводя итог, можно сказать, что при
создании функции PL/pgSQL:
1) план выполнения не сохраняется;
2) никакие проверки на наличие таблиц, столбцов или других функций
не выполняются;
3)
вы не знаете, работает ваша функция или нет, пока не выполните ее
(и, как правило, не один раз, если есть несколько путей выполнения).
Еще одно важное свойство функций PostgreSQL, которое следует из пре-
дыдущего объяснения, состоит в том, что функции являются «атомарными»
в нескольких разных смыслах. Во-первых (к разочарованию пользователей
Oracle), вы не можете начинать транзакции внутри функций PostgreSQL,
поэтому инструкции DML – это всегда «все или ничего». Во-вторых, когда
оптимизируется план выполнения запроса, планировщик PostgreSQL ничего
не знает о пользовательских функциях. Например, выполните
EXPLAIN SELECT num_passengers(13)
План выполнения будет выглядеть примерно так:
Result (cost=0.00..0.26 rows=1 width=4)
Если
вам нужно выяснить, какие планы используются для выполнения
запросов внутри функции, вам нужно будет подставить какие-нибудь фак-
тические значения вместо параметров и для каждой инструкции выполнить
команду
EXPLAIN
.
Одно из ключевых слов в команде
CREATE
FUNCTION
(помните, мы перечисли-
ли не все из них!) –
COST
. Оно позволяет разработчику явно установить стои-
мость выполнения функции, которая будет использоваться оптимизатором.
Значение по умолчанию – 100, и мы не рекомендуем изменять его, если у вас
нет на то действительно веских причин.