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