PREPARE
PREPARE
准备要执行的语句。
概要
PREPARE name [ (datatype [, ...] ) ] AS statement
描述
PREPARE创建一个预编译语句。 预编译语句是可用于优化性能的服务器端对象。 当执行PREPARE语句时,将解析、分析和重写指定的语句。 随后发出EXECUTE命令时,将计划并执行预编译语句。 这种分工避免了重复的解析分析工作,同时允许执行计划取决于所提供的特定参数值。
预编译语句可以采用参数:执行语句时将用值替换。 创建预编译语句时,请使用$1,$2等按位置引用参数。 可以选择指定相应的参数数据类型列表。 如果未指定参数的数据类型或将其声明为未知,则从首次使用该参数的上下文中推断该类型(如果可能)。 执行该语句时,请在EXECUTE语句中指定这些参数的实际值。
预编译语句仅在当前数据库会话期间有效。 会话结束时,预编译语句将废弃,因此必须在重新使用之前重新创建它。 这也意味着单个预编译语句不能被多个同时的数据库客户端使用。 但是,每个客户端可以创建自己预编译语句来使用。 可以使用DEALLOCATE命令手动清除预编译语句。
当使用单个会话执行大量相似的语句时,预备语句具有最大的性能优势。 如果语句计划或重写很复杂,那么性能差异将特别显着,例如,查询涉及多个表的连接或需要应用多个规则。 如果该语句的计划和重写相对简单,但是执行成本相对较高,则预编译语句的性能优势将不太明显。
参数
- name
- 为此特定的预编译语句提供的任意名称。 它在单个会话中必须是唯一的,并随后用于执行或取消分配先前预编译语句。
- datatype
- 预编译语句的参数的数据类型。 如果未指定特定参数的数据类型或将其指定为未知,则将从首次使用该参数的上下文中推断出来。 要在预编译语句本身中引用参数,请使用$1,$2等。
- statement
- 任何SELECT,INSERT,UPDATE,DELETE或VALUES语句。
注解
如果预编译语句执行了足够的时间,则服务器可能最终决定保存并重新使用通用计划,而不是每次都重新计划。 如果预编译语句没有参数,这将立即发生; 否则,仅当通用计划看起来并不比依赖于特定参数值的计划昂贵得多时,它才会发生。 通常,仅当估计查询的性能对提供的特定参数值相当不敏感时,才会选择通用计划。
要检查Greenplum数据库用于预编译语句的查询计划,请使用EXPLAIN。 如果正在使用通用计划,它将包含参数符号$n, 而自定义计划将使用当前的实际参数值替代它。
有关查询计划和Greenplum数据库为此目的收集的统计信息的更多信息,请参阅ANALYZE文档。
尽管预编译语句的主要目的是避免重复分析和规划语句, 但只要语句中使用的数据库对象自上次使用预处理语句以来发生了定义(DDL)更改, Greenplum都会在使用之前强制重新分析和重新规划语句。 同样,如果search_path的值从一个更改为下一个,则将使用新的search_path重新解析该语句。 (后一种行为自Greenplum 6起是新的。) 这些规则使用预编译语句在语义上几乎等同于一次又一次地重新提交相同的查询文本, 这在语义上几乎等同于使用预编译语句, 但是如果不更改对象定义,则可以提高性能,特别是如果最佳计划在不同用途之间保持不变。 语义对等不完美的情况的一个示例是,如果该语句使用不合格的名称引用表, 然后在较早出现在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语句创建一个预编译语句,然后执行它。 请注意,未指定第二个参数的数据类型,因此可以从使用$2的上下文中推断出它:
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);
兼容性
SQL标准包括一个PREPARE语句,但仅用于嵌入式SQL。 此版本的PREPARE语句还使用了一些不同的语法。