Un plan de ejecución PostgreSQL se obtiene usando el comando explain
antes de la sentencia SQL. Sin embargo, existe una limitación importante: las sentencias SQL con las variables bind (por ejemplo, $1
, $2, etc.)
no pueden ser explicadas de esta manera; se necesita utilizar prepare primero:
PREPARE stmt(int) AS SELECT $1
PostgreSQL usa "$n
" para las variables bind. La capa de abstracción de su base de datos podría ocultarlo así que se pueden utilizar signos de interrogación como lo define el estándar SQL.
La ejecución de la sentencia preparada puede mostrarse así:
EXPLAIN EXECUTE stmt(1)
Hasta PostgreSQL 9.1, el plan de ejecución se crea con el comando prepare
y por lo tanto no podría considerar los valores actuales proporcionados por el comando execute
. Desde PostgreSQL 9.2, la creación del plan de ejecución se pospone hasta la ejecución y así se pueden considerar los valores reales para las variables bind.
Nota
Las sentencias sin variables bind pueden explicarse directamente:
EXPLAIN SELECT 1
En este caso, el optimizador tiene siempre que considerar los valores reales durante la planificación de la sentencia.
La salida del plan de ejecución es como sigue:
QUERY PLAN
------------------------------------------
Result (cost=0.00..0.01 rows=1 width=0)
La salida tiene información similar a los planes de ejecución de Oracle que se han visto a lo largo de este libro: el nombre de la operación (“Result”), el coste asociado, la estimación del número de filas y la anchura de la fila esperada.
PostgreSQL muestra dos valores de coste. El primero es el coste al inicio; el segundo es el coste total para la ejecución si se recuperan todas las filas. El plan de ejecución de la base de datos Oracle muestra solamente el segundo valor.
El comando PostgreSQL explain
tiene dos opciones. La primera opción es VERBOSE
y provee información adicional como el nombre de las tablas completamente calificadas; sin embargo, VERBOSE
generalmente no resulta una opción muy útil.
La segunda opción es ANALYZE
. Aunque se emplea mucho, no recomiendo tener la costumbre de utilizarlo de forma automática porque ejecuta realmente la sentencia. Es en gran parte inofensivo con las sentencias select
, pero ¡ojo!, porque modifican los datos cuando se usan insert
, update
o delete
. Para evitar el riesgo de modificar los datos de forma accidental, se debe incluir dentro de una transacción y después realizar rollback.
Aviso
explain analyze
ejecuta la sentencia, incluso si la sentencia es un insert
, update
o delete
.
La opción ANALYZE
ejecuta la sentencia, muestra el tiempo real y el número de filas. Es muy valiosa buscando la causa de una estimación de cardinalidad incorrecta (row count estimates):
BEGIN
EXPLAIN (ANALYZE, BUFFERS, SETTINGS) EXECUTE stmt(1)
QUERY PLAN
--------------------------------------------------
Result (cost=0.00..0.01 rows=1 width=4)
(actual time=0.001..0.002 rows=1 loops=1)
Settings: random_page_cost = '1.1'
Planning Time: 0.032 ms
Execution Time: 0.078 ms
ROLLBACK
Observa que el plan está formateado para tener una mejor adaptación sobre la página. PostgreSQL imprime los valores reales (“actuals”) en la misma fila como los valores estimados.
El número de filas es sólo el valor que se muestra en ambas partes, tanto en la cantidad estimada como en la real. Eso permite encontrar con rapidez las estimaciones incorrectas de cardinalidad.
Por último, las sentencias preparadas se deben cerrar de nuevo:
DEALLOCATE stmt