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

SELECTINSERTUPDATEDELETEVALUES语句之一。

注意

在一些情况下,PostgreSQL为一个预备语句生成的查询 规划可能还不如按照普通方法提交并执行的查询生成的规划好。 这是因为该查询在被规划的时候(也是优化器判断最优查询规划的时候), 在查询中声明的任何参数的实际数值都还不可见。 PostgreSQL在表中收集数据分布的统计,而且可以利用查 询中的常量来猜测执行查询的可能结果。 因为这些数据在规划的时候还是未知,所以,得到的规划可能很差劲。 使用EXPLAIN查看PostgreSQL 为预备语句选取的查询计划。

有关查询规划和PostgreSQL为查询优化的目的收集统计的更多信息, 参阅ANALYZE文档。

可以通过查询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。 PostgreSQL实现的PREPARE语句的语法也略有不同。

又见

DEALLOCATE, EXECUTE