PREPARE

PREPARE — подготовить оператор для исполнения

Синтаксис

PREPARE имя [ ( тип_данных [, ...] ) ] AS оператор

Описание

Команда PREPARE создает подготовленный оператор. Подготовленный оператор — это объект на стороне сервера, который можно использовать для оптимизации производительности. При выполнении команды PREPARE указанный оператор разбирается, анализируется и перезаписывается. При последующем выполнении команды EXECUTE подготовленный оператор планируется и исполняется. Это разделение труда предотвращает повторный синтаксический анализ запроса, при этом позволяя выбрать наилучший план выполнения в зависимости от определенных значений параметров.

Подготовленные операторы могут принимать параметры: значения, которые подставляются в оператор при его выполнении. При создании подготовленного оператора к этим параметрам можно обращаться по порядковому номеру, используя запись $1, $2 и т. д. При необходимости можно указать соответствующий список типов данных параметров. Если тип данных параметра не указан или объявлен как unknown (неизвестный), тип выводится из контекста, в котором произошло первое обращение к данному параметру (если это возможно). При выполнении оператора укажите команде EXECUTE фактические значения этих параметров. Дополнительную информацию об этом см. в разделе EXECUTE.

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

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

Параметры

имя

Произвольное имя, данное этому конкретному подготовленному оператору. Оно должно быть уникальным в пределах одного сеанса и впоследствии используется для выполнения или освобождения ранее подготовленного оператора.

тип_данных

Тип данных параметра для подготовленного оператора. Если тип данных конкретного параметра не определен или указан как unknown, он будет выведен из контекста, в котором произошло первое обращение к этому параметру. Для обращения к параметрам в самом подготовленном операторе используйте запись $1, $2 и т. д.

оператор

Любой оператор SELECT, INSERT, UPDATE, DELETE или VALUES.

Примечания

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

По умолчанию (то есть когда plan_cache_mode установлен в auto), сервер автоматически выберет, какой план использовать для подготовленного оператора с параметрами: общий или специализированный. Текущее правило состоит в том, что первые пять исполнений выполняются со специализированными планами, и рассчитывается средняя расчетная стоимость этих планов. Затем создается общий план, и его расчетная стоимость сравнивается со средней стоимостью специализированного плана. Последующие выполнения используют общий план, если его стоимость по сравнению со стоимостью специализированных не настолько велика, чтобы делать повторное перепланирование.

Эту логику можно переопределить, заставляя сервер использовать либо только общие, либо специализированные планы, установив для параметра plan_cache_mode значение force_generic_plan или force_custom_plan соответственно. Этот параметр в первую очередь полезен, если по какой-то причине плохо работает оценка общего плана, так как позволяет выбрать его, даже если его фактическая стоимость намного больше, чем у специализированного плана.

Чтобы узнать план запроса, который QHB выбирает для подготовленного оператора, используйте команду EXPLAIN, например:

EXPLAIN EXECUTE имя(значения_параметров);

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

Дополнительную информацию о планировании запросов и статистике, собранной QHB для этой цели, см. в документации по команде ANALYZE.

Хотя основной целью подготовленных операторов является предотвращение повторного разбора и планирования оператора, QHB будет принудительно заново анализировать и планировать выполнение оператора всякий раз, когда используемые в операторе объекты базы данных подвергаются изменениям определения (DDL) с момента предыдущего использования подготовленного оператора. Кроме того, если значение search_path изменяется от одного использования к другому, оператор будет повторно разобран с новым search_path. С этими правилами использование подготовленного оператора по сути почти не отличается от выполнения одного и того же запроса снова и снова, но с преимуществом производительности, если определения объектов не меняются (особенно если оптимальный план из раза в раз остается неизменным). Примером случая, когда различия всё же могут проявиться, служит то, что если оператор обращается к таблице по неполному имени, а затем новая таблица с таким же именем создается в схеме, стоящей в пути search_path раньше, автоматический пересмотр запроса не происходит, так как ни один используемый в операторе объект не изменился. Однако если какое-то другое изменение вызывает повторный анализ, при последующем выполнении запроса будет задействована новая таблица.

Получить список всех доступных в сеансе подготовленных операторов можно, обратившись к системному представлению pg_prepared_statements.

Примеры

Создание подготовленного оператора для команды INSERT, который затем выполняется:

PREPARE fooplan (int, text, bool, numeric) AS
    INSERT INTO foo VALUES($1, $2, $3, $4);
EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00);

Создание подготовленного оператора для команды SELECT, который затем выполняется:

PREPARE usrrptplan (int) AS
    SELECT * FROM users u, logs l WHERE u.usrid=$1 AND u.usrid=l.usrid
    AND l.date = $2;
EXECUTE usrrptplan(1, current_date);

В этом примере тип данных второго параметра не указывается, поэтому он выводится из контекста, в котором используется $2.

Совместимость

Стандарт SQL включает команду PREPARE, но она предназначена только для использования во встраиваемом SQL. Эта версия команды PREPARE также использует несколько иной синтаксис.

См. также

DEALLOCATE, EXECUTE