PREPARE

Подготавливает запрос к выполнению.

Обзор

PREPARE <name> [ (<data_type> [, ...] ) ] AS <statement>

Описание

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

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

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

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

Параметры

  • name
    • Произвольное имя данного подготовленного оператора. Оно должно быть уникальным в пределах одной сессии и в дальнейшем используется для выполнения или удаления ранее подготовленного оператора.
  • data_type
    • Тип данных параметра подготовленного оператора. Если тип данных конкретного параметра не указан или указан как unknown, он будет выведен из контекста первого использования параметра. Для ссылки на параметры внутри самого подготовленного оператора используйте $1, $2 и т.д.
  • statement
    • Любой оператор SELECT, INSERT, UPDATE, DELETE или VALUES.

Замечания

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

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

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

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

EXPLAIN EXECUTE <name>(<parameter_values>);

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

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

Хотя основная цель подготовленного оператора — избежать повторного анализа и планирования, Database принудительно выполняет повторный анализ и перепланирование оператора перед его использованием, если определения объектов базы данных, используемых в операторе, были изменены (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 и его выполнение. Обратите внимание, что тип данных второго параметра не указан, поэтому он выводится из контекста использования $2:

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);

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

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

См. также

EXECUTE, DEALLOCATE