PREPARE

PREPARE — prepara una sentencia para su ejecución

Synopsis

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

Descripción

PREPARE crea una sentencia preparada. Una sentencia preparada es un objeto en el lado del servidor que se puede utilizar para optimizar el rendimiento. Cuando se ejecuta la sentencia PREPARE, la sentencia especificada se analiza sintácticamente, se analiza y se reescribe. Cuando posteriormente se emite un comando EXECUTE, la sentencia preparada se planifica y se ejecuta. Esta división del trabajo evita el análisis sintáctico repetitivo, al tiempo que permite que el plan de ejecución dependa de los valores de los parámetros específicos suministrados.

Las sentencias preparadas pueden recibir parámetros: valores que se sustituyen en la sentencia cuando esta se ejecuta. Al crear la sentencia preparada, haz referencia a los parámetros por su posición, utilizando $1, $2, etc. Opcionalmente, se puede especificar una lista correspondiente de tipos de datos de los parámetros. Cuando el tipo de datos de un parámetro no se especifica o se declara como unknown, el tipo se infiere del contexto en el que se hace referencia al parámetro por primera vez (si es posible). Al ejecutar la sentencia, especifica los valores reales de estos parámetros en la sentencia EXECUTE. Consulta EXECUTE para obtener más información al respecto.

Las sentencias preparadas solo duran el tiempo de la sesión actual de la base de datos. Cuando la sesión termina, la sentencia preparada se olvida, por lo que debe volver a crearse antes de volver a utilizarse. Esto también significa que una misma sentencia preparada no puede ser utilizada por múltiples clientes de bases de datos simultáneos; sin embargo, cada cliente puede crear su propia sentencia preparada para usarla. Las sentencias preparadas se pueden limpiar manualmente utilizando el comando DEALLOCATE.

Las sentencias preparadas tienen potencialmente la mayor ventaja de rendimiento cuando se utiliza una sola sesión para ejecutar un gran número de sentencias similares. La diferencia de rendimiento será particularmente significativa si las sentencias son complejas de planificar o reescribir, por ejemplo, si la consulta involucra una unión de muchas tablas o requiere la aplicación de varias reglas. Si la sentencia es relativamente simple de planificar y reescribir pero relativamente costosa de ejecutar, la ventaja de rendimiento de las sentencias preparadas será menos notoria.

Parámetros

name

Un nombre arbitrario dado a esta sentencia preparada en particular. Debe ser único dentro de una sola sesión y se utiliza posteriormente para ejecutar o liberar una sentencia previamente preparada.

data_type

El tipo de datos de un parámetro de la sentencia preparada. Si el tipo de datos de un parámetro en particular no se especifica o se especifica como unknown, se inferirá del contexto en el que se hace referencia al parámetro por primera vez. Para hacer referencia a los parámetros en la propia sentencia preparada, utiliza $1, $2, etc.

statement

Cualquier sentencia SELECT, INSERT, UPDATE, DELETE, MERGE o VALUES.

Notas

Una sentencia preparada se puede ejecutar con un plan genérico (generic plan) o con un plan personalizado (custom plan). Un plan genérico es el mismo en todas las ejecuciones, mientras que un plan personalizado se genera para una ejecución específica utilizando los valores de los parámetros dados en esa llamada. El uso de un plan genérico evita la sobrecarga de la planificación, pero en algunas situaciones un plan personalizado será mucho más eficiente de ejecutar porque el planificador puede hacer uso del conocimiento de los valores de los parámetros. (Por supuesto, si la sentencia preparada no tiene parámetros, entonces esto es irrelevante y siempre se utiliza un plan genérico).

Por defecto (es decir, cuando plan_cache_mode está establecido en auto), el servidor elegirá automáticamente si utilizar un plan genérico o personalizado para una sentencia preparada que tenga parámetros. La regla actual para esto es que las primeras cinco ejecuciones se realizan con planes personalizados y se calcula el costo estimado promedio de esos planes. Luego se crea un plan genérico y su costo estimado se compara con el costo promedio del plan personalizado. Las ejecuciones posteriores utilizan el plan genérico si su costo no es tanto mayor que el costo promedio del plan personalizado como para hacer que parezca preferible volver a planificar repetidamente.

Esta heurística se puede anular, forzando al servidor a utilizar planes genéricos o personalizados, estableciendo plan_cache_mode en force_generic_plan o force_custom_plan respectivamente. Esta configuración es útil principalmente si la estimación del costo del plan genérico está muy errada por alguna razón, lo que permite elegirlo a pesar de que su costo real sea mucho mayor que el de un plan personalizado.

Para examinar el plan de consulta que PostgreSQL está utilizando para una sentencia preparada, utiliza EXPLAIN, por ejemplo:

EXPLAIN EXECUTE name(parameter_values);

Si se está utilizando un plan genérico, contendrá los símbolos de los parámetros $n, mientras que un plan personalizado tendrá sustituidos en él los valores de los parámetros suministrados.

Para obtener más información sobre la planificación de consultas y las estadísticas recopiladas por PostgreSQL para ese propósito, consulta la documentación de ANALYZE.

Aunque el objetivo principal de una sentencia preparada es evitar el análisis sintáctico y la planificación repetidos de la sentencia, PostgreSQL forzará el reanálisis y la replanificación de la sentencia antes de utilizarla siempre que los objetos de la base de datos utilizados en la sentencia hayan sufrido cambios de definición (DDL) o sus estadísticas del planificador se hayan actualizado desde el uso anterior de la sentencia preparada. Además, si el valor de search_path cambia de un uso al siguiente, la sentencia se volverá a analizar utilizando el nuevo search_path. (Este último comportamiento es nuevo a partir de PostgreSQL 9.3). Estas reglas hacen que el uso de una sentencia preparada sea semánticamente casi equivalente a volver a enviar el mismo texto de consulta una y otra vez, pero con un beneficio de rendimiento si no se cambian las definiciones de los objetos, especialmente si el mejor plan sigue siendo el mismo en todos los usos. Un ejemplo de un caso en el que la equivalencia semántica no es perfecta es si la sentencia se refiere a una tabla por un nombre no calificado, y luego se crea una nueva tabla con el mismo nombre en un esquema que aparece antes en el search_path. En este caso, no se producirá ningún reanálisis automático ya que ningún objeto utilizado en la sentencia cambió. Sin embargo, si algún otro cambio fuerza un reanálisis, se hará referencia a la nueva tabla en los usos posteriores.

Puedes ver todas las sentencias preparadas disponibles en la sesión consultando la vista de sistema pg_prepared_statements.

Ejemplos

Crea una sentencia preparada para una sentencia INSERT y luego ejecútala:

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

Crea una sentencia preparada para una sentencia SELECT y luego ejecútala:

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);

En este ejemplo, el tipo de datos del segundo parámetro no está especificado, por lo que se infiere del contexto en el que se utiliza $2.

Compatibilidad

El estándar SQL incluye una sentencia PREPARE, pero es solo para su uso en SQL embebido (embedded SQL). Esta versión de la sentencia PREPARE también utiliza una sintaxis algo diferente.

Véase también

DEALLOCATE, EXECUTE