PREPARE

Name

PREPARE -- 为执行准备一个语句

Synopsis

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

描述

PREPARE创建一个预备语句。预备语句是一种 服务器端对象,它可以被用来优化性能。当 PREPARE语句被执行时,指定的语句会被解析、 分析并且重写。当后续发出一个EXECUTE命令 时,该预备语句会被规划并且执行。这种工作的划分避免了重复性的解析分析 工作,不过允许执行计划依赖所提供的特定参数值。

预备语句可以接受参数:在执行时会被替换到语句中的值。在创建预备语句时, 可以用位置引用参数,如$1$2等。也可以选择性 地指定参数数据类型的一个列表。当一个参数的数据类型没有被指定或者被声明 为unknown时,其类型会从该参数被使用的环境中推知( 如果可能)。在执行该语句时,在EXECUTE语句 中为这些参数指定实际值。更多有关于此的信息可参考EXECUTE

预备语句只在当前数据库会话期间存在。当会话结束时,预备语句会消失,因此 在重新使用之前必须重新建立它。这也意味着一个预备语句不能被多个数据库客 户端同时使用。不过,每一个客户端可以创建它们自己的预备语句来使用。预备 语句可以用DEALLOCATE命令手工清除。

当一个会话要执行大量类似语句时,预备语句能够得到最大性能优势。如果该语 句很复杂(难于规划或重写),例如,如果查询涉及很 多表的连接或者要求应用多个规则,性能差异将会特别明显。如果语句相对比较 容易规划和重写,但是执行起来开销相对较大,那么预备语句的性能优势就不那 么显著了。

参数

name

给这个特定预备语句的任意名称。它在一个会话中必须唯一并且后续将被 用来执行或者清除一个之前准备好的语句。

data_type

预备语句一个参数的数据类型。如果一个特定参数的数据类型没有被 指定或者被指定为unknown,将从该参数被使用 的环境中推得。要在预备语句本身中引用参数,可以使用 $1$2等。

statement

任何SELECTINSERTUPDATEDELETE或者VALUES语句。

注解

如果一个预备语句被执行足够多次,服务器可能最终决定保存并且重用一个一般 计划而不是每次重新规划。如果预备语句没有参数,这将会立刻发生。否则,只 有在一般计划不比依赖于特定参数值的计划昂贵太多的时候才会发生。通常,只 有查询的性能被估计为对提供的特定参数值相当不敏感时才会选择一般计划。

要检查被PostgreSQL用于一个预备语句的 查询计划,可以使用EXPLAIN。如果用了一个一般计划, 它将包含参数符号$n,而一个自定义计 划将具有替换到其中的当前实参。

更多关于查询规划以及PostgreSQL为此所 收集的统计信息的内容,请见ANALYZE文档。

尽管预备语句主要是为了避免重复对语句进行解析分析以及规划,但是只要 上一次使用该预备语句后该语句中用到的数据库对象发生了定义性(DDL)改变, PostgreSQL将会对该语句强制进行重新分析和重新规划。 还有,如果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语句也使用了一种有些不同的 语法。

另见

DEALLOCATE, EXECUTE