# 准备

PREPARE — 准备执行语句

# 概要

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

# 描述

准备创建一个准备好的语句。准备好的语句是可用于优化性能的服务器端对象。当。。。的时候准备语句被执行,指定的语句被解析、分析和重写。当一个执行随后发出命令,计划并执行准备好的语句。这种分工避免了重复的解析分析工作,同时允许执行计划依赖于提供的特定参数值。

准备好的语句可以带参数:在执行语句时替换到语句中的值。创建准备好的语句时,按位置引用参数,使用1美元,2美元等。可以选择指定相应的参数数据类型列表。当参数的数据类型未指定或声明为未知,类型是从第一次引用参数的上下文中推断出来的(如果可能的话)。执行语句时,在执行陈述。参考执行了解更多信息。

准备好的语句仅在当前数据库会话期间持续。当会话结束时,准备好的语句被遗忘,因此必须重新创建它才能再次使用。这也意味着单个准备好的语句不能被多个同时的数据库客户端使用;但是,每个客户都可以创建自己的准备好的语句来使用。准备好的语句可以使用手动清理解除分配命令。

当使用单个会话执行大量类似语句时,准备好的语句可能具有最大的性能优势。如果语句计划或重写很复杂,例如,如果查询涉及多个表的连接或需要应用多个规则,则性能差异将特别显着。如果语句的计划和重写相对简单,但执行起来相对昂贵,则准备好的语句的性能优势将不那么明显。

# 参数

姓名

给这个特定的准备好的语句的任意名称。它在单个会话中必须是唯一的,并且随后用于执行或取消分配先前准备好的语句。

数据类型

准备好的语句的参数的数据类型。如果特定参数的数据类型未指定或指定为未知,它将从第一次引用参数的上下文中推断出来。要引用准备好的语句本身中的参数,请使用1美元,2美元, 等等。

陈述

任何选择,插入,更新,删除, 要么价值观陈述。

# 笔记

准备好的语句可以使用以下任一方式执行通用计划或一个定制计划.通用计划在所有执行中都是相同的,而使用该调用中给定的参数值为特定执行生成自定义计划。使用通用计划避免了计划开销,但在某些情况下,自定义计划的执行效率更高,因为计划者可以利用参数值的知识。(当然,如果准备好的语句没有参数,那么这是没有实际意义的,总是使用通用计划。)

默认情况下(即,当计划_缓存_modeis set toauto), the server will automatically choose whether to use a generic or custom plan for a prepared statement that has parameters. The current rule for this is that the first five executions are done with custom plans and the average estimated cost of those plans is calculated. Then a generic plan is created and its estimated cost is compared to the average custom-plan cost. Subsequent executions use the generic plan if its cost is not so much higher than the average custom-plan cost as to make repeated replanning seem preferable.

This heuristic can be overridden, forcing the server to use either generic or custom plans, by settingplan_cache_modetoforce_generic_planorforce_custom_planrespectively. This setting is primarily useful if the generic plan's cost estimate is badly off for some reason, allowing it to be chosen even though its actual cost is much more than that of a custom plan.

To examine the query plan PostgreSQL is using for a prepared statement, useEXPLAIN, for example

EXPLAIN EXECUTE name(parameter_values);

If a generic plan is in use, it will contain parameter symbols$*n*, while a custom plan will have the supplied parameter values substituted into it.

For more information on query planning and the statistics collected by PostgreSQL for that purpose, see theANALYZEdocumentation.

Although the main point of a prepared statement is to avoid repeated parse analysis and planning of the statement, PostgreSQL will force re-analysis and re-planning of the statement before using it whenever database objects used in the statement have undergone definitional (DDL) changes or their planner statistics have been updated since the previous use of the prepared statement. Also, if the value ofsearch_pathchanges from one use to the next, the statement will be re-parsed using the newsearch_path(从PostgreSQL 9.3开始,后一种行为是新的。)这些规则使用预先准备好的语句,在语义上几乎等同于反复提交相同的查询文本,但如果不更改对象定义,尤其是如果最佳计划在不同的使用中保持不变,则会带来性能优势。语义等价性不完美的一个例子是,如果语句以非限定名称引用表,然后在前面出现的模式中创建一个同名的新表搜索路径,不会自动重新分析,因为语句中使用的对象没有更改。但是,如果其他一些更改强制重新解析,则新表将在后续使用中被引用。

通过查询pg_准备的_声明系统视图。

# 例子

为项目创建准备好的语句插入语句,然后执行它:

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

为项目创建准备好的语句选择语句,然后执行它:

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标准包括准备语句,但它仅用于嵌入式SQL。这个版本的准备语句也使用了一些不同的语法。

# 另见

解除分配,处决