PREPARE
Эта страница переведена при помощи нейросети GigaChat.
PREPARE
- создание подготовленного оператора.
Синтаксис
PREPARE name [ ( data_type [, ...] ) ] AS statement
Описание
PREPARE
создает подготовленный оператор. Подготовленный оператор является объектом на стороне сервера, предназначенный для оптимизации производительности запросов. Когда выполняется команда PREPARE
, указанный SQL-запрос проходит этапы синтаксического разбора, анализа и переписывания. Позднее, при выполнении команды EXECUTE
, это подготовленное выражение планируется и выполняется. Такое разделение выполнения позволяет избежать многократного анализа выражения, при этом учитывая конкретные значения параметров при создании плана выполнения.
Подготовленные операторы могут использовать параметры — значения, которые подставляются в оператор при его исполнении. При создании подготовленного оператора параметры указываются по порядковым номерам — $1
, $2
, и так далее. Можно также указать соответствующие типы данных параметров. Если тип данных параметра не указан или явно указан как unknown
, тип будет выведен автоматически из контекста первого использования параметра, если это возможно. При выполнении оператора необходимо передать конкретные значения параметров в команде EXECUTE
. Подробности смотрите в описании команды EXECUTE.
Подготовленные операторы существуют только в течение текущей сессии с базой данных. Когда сессия завершается, подготовленные операторы удаляются и должны быть созданы заново при следующем подключении. Это также означает, что один и то же подготовленный оператор не может быть использовано несколькими клиентами одновременно. Однако каждый клиент может создать свой собственный оператор для использования в своей сессии. Подготовленные операторы можно удалить вручную с помощью команды DEALLOCATE.
Наибольший прирост производительности от использования подготовленных операторов достигается в тех случаях, когда в рамках одной сессии выполняется множество схожих по структуре SQL-запросов. Особенно это актуально, если запросы сложны с точки зрения построения плана или переписывания, например, содержат объединения (JOIN
) большого числа таблиц или требуют применения нескольких правил (RULE
). Если запрос, наоборот, прост с точки зрения построения плана, но тяжел в плане выполнения, то эффект от использования подготовленных операторов будет менее заметен.
Параметры
name
- Произвольное имя, присваиваемое данному подготовленному оператору.
Имя должно быть уникальным в рамках одной сессии. Оно используется позже для выполнения (
EXECUTE
) или удаления (DEALLOCATE
) подготовленного оператора.
data_type
- Тип данных параметра. Если тип не указан или задан как
unknown
, PostgreSQL попытается вывести его из контекста первого использования параметра в теле оператора. Внутри подготовленного оператора параметры обозначаются как$1
,$2
, и так далее.
statement
- SQL-запрос любого из следующих видов:
SELECT
,INSERT
,UPDATE
,DELETE
,MERGE
илиVALUES
.
Примечания
Подготовленный оператор может выполняться с использованием обобщенного плана или специализированного плана. Обобщенный план создается один раз и используется для всех последующих выполнений выражения. Специализированный план создается заново каждый раз на основе конкретных значений параметров.
Использование обобщенного плана позволяет сократить издержки на повторное построение плана, но в ряде случаев специализированный план может быть значительно более эффективным, так как планировщик может учитывать конкретные значения параметров при выборе оптимального варианта выполнения.
По умолчанию, если параметр plan_cache_mode установлен в значение auto
, сервер сам решает, какой тип плана использовать для подготовленного выражения, содержащего параметры.
Текущий алгоритм следующий:
- Первые пять выполнений — со специализированным планом.
- Вычисляется средняя оценочная стоимость этих пяти выполнений.
- Создается обобщенный план, и его оценочная стоимость сравнивается со средней стоимостью специализированных планов.
- Если обобщенный план не оказывается существенно хуже, он используется для всех последующих выполнений.
Логику выбора плана можно переопределить, установив параметр plan_cache_mode
в значение force_generic_plan
(принудительно обобщенный план) или force_custom_plan
(принудительно специализированный план). Такая настройка может быть полезна в ситуациях, когда оценка стоимости обобщенного плана ошибочна, и он выбирается сервером несмотря на то, что на практике он оказывается менее эффективным.
Чтобы просмотреть план выполнения подготовленного выражения, можно использовать команду EXPLAIN
, например:
EXPLAIN EXECUTE name(parameter_values);
Если используется обобщенный план, то в выводе будут отображаться параметры в виде $n
. Если используется специализированный план, то значения параметров будут подставлены непосредственно в план.
Дополнительную информацию о планировании запросов и о статистике, собираемой PostgreSQL для этих целей, можно найти в описании команды ANALYZE.
Хотя основное назначение подготовленного выражения — избежать повторного синтаксического анализа и планирования, PostgreSQL может принудительно выполнить повторную переработку оператора перед его использованием, если:
- объекты базы данных, используемые в выражении, были изменены (DDL-операции);
- была обновлена статистика, используемая планировщиком;
- между выполнениями изменился параметр search_path.
Поведение, связанное с search_path, актуально начиная с версии PostgreSQL 9.3. Эти правила обеспечивают семантическую эквивалентность подготовленного оператора повторной отправке SQL-запроса как текста, но при этом позволяют достичь преимущества в производительности в случаях, когда определения объектов не меняются и подходящий план остается тем же.
Пример исключения из этой эквивалентности: если в выражении указано имя таблицы без схемы, а затем в схеме, стоящей раньше в search_path
, создается новая таблица с тем же именем, то повторного разбора не произойдет, поскольку PostgreSQL не считает, что объект изменился. Но, если что-то другое вызовет повторный разбор, в дальнейшем будет использоваться уже новая таблица.
Список всех подготовленных выражений, доступных в текущей сессии, можно посмотреть с помощью представления 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
использует несколько иной синтаксис.