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