PREPARE — prepara una sentencia para su ejecución
PREPAREname[ (data_type[, ...] ) ] ASstatement
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.
nameUn 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.
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 EXECUTEname(parameter_values);
Si se está utilizando un plan genérico, contendrá los símbolos de los parámetros
$, mientras que un plan personalizado
tendrá sustituidos en él los valores de los parámetros suministrados.
n
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.
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.
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.