Blog de Analytics y Gestión de Datos

22/05/2025 | Ing. Fabiana Sasia

Explain Plan en PostgreSQL: Análisis, Optimización y Herramientas 

Cuando una consulta SQL no responde como esperamos, necesitamos saber qué está ocurriendo detrás de escena. Hoy hablaremos sobre una herramienta clave que permite comprender el rendimiento de nuestras consultas en PostgreSQL: el Explain Plan. Este artículo te ayudará a descubrir cómo se interpreta, qué métricas ofrece y una comparativa con las herramientas de SQL Server. Además, información sobre  herramientas alternativas para análisis avanzados.

¿Cómo funciona una consulta?

En cualquier sistema de base de datos relacional, entender el comportamiento de una consulta es crucial para optimizar el rendimiento y evitar cuellos de botella. PostgreSQL nos brinda la herramienta EXPLAIN (y EXPLAIN ANALYZE) para revelar cómo el optimizador de consultas planea ejecutar una instrucción SQL. Esta visibilidad resulta esencial, especialmente cuando se trata de grandes volúmenes de datos o sistemas en producción.

Hay cuatro recursos principales que consume una consulta: memoria, CPU, disco y red. El más costoso de estos es el disco, debido a la latencia implicada en las operaciones de lectura y escritura. Por ello, saber cuántas lecturas físicas realiza una consulta, cuánto CPU utiliza y si está usando índices o no, puede hacer la diferencia entre un sistema eficiente y uno inestable.

¿Qué es EXPLAIN y EXPLAIN ANALYZE?

El comando EXPLAIN en PostgreSQL muestra el plan de ejecución que el optimizador ha generado para una consulta. Cuando se utiliza junto a ANALYZE, también se ejecuta la consulta y se reporta el tiempo real de ejecución, cantidad de filas, número de lecturas de disco, tiempo de CPU, y más.

Ejemplo:

EXPLAIN ANALYZE SELECT * FROM empleados WHERE salario > 5000;

Este comando devuelve información como:

  • Tipo de join utilizado
  • Uso de índices o escaneos secuenciales
  • Cantidad de bloques leídos
  • Tiempo de ejecución total

¿Cómo usar EXPLAIN y qué métricas devuelve?

El comando EXPLAIN en PostgreSQL nos permite entender cómo el optimizador de consultas planea ejecutar una instrucción SQL. Cuando lo combinamos con la cláusula ANALYZE, obtenemos un resultado real de la ejecución, no sólo la estimación.

📌 Sintaxis básica

EXPLAIN ANALYZE SELECT * FROM empleados WHERE departamento_id = 10;

🧠 ¿Qué devuelve exactamente EXPLAIN ANALYZE?

El resultado será algo como lo siguiente:

text

Seq Scan on empleados  (cost=0.00..35.50 rows=5 width=128) (actual time=0.015..0.020 rows=3 loops=1)

  Filter: (departamento_id = 10)

  Rows Removed by Filter: 97

Planning Time: 0.080 ms

Execution Time: 0.045 ms

Ahora desglosamos cada parte:

🔍 Análisis línea por línea

 

Elemento

Explicación

Seq Scan on empleados

PostgreSQL está utilizando un escaneo secuencial sobre la tabla empleados, lo que significa que lee todas las filas una por una.

cost=0.00..35.50

Este es el costo estimado de ejecución: desde el mínimo (inicio del plan) hasta el total. Se expresa en unidades arbitrarias basadas en I/O y CPU, según las estadísticas internas.

rows=5

Número estimado de filas que se devolverán. Esta cifra viene del planificador, no de la ejecución real.

width=128

Tamaño promedio (en bytes) de cada fila. En este caso, 128 bytes.

actual time=0.015..0.020

Tiempos reales de ejecución: cuándo empezó y terminó el nodo del plan.

rows=3

Cantidad real de filas devueltas.

loops=1

Número de veces que se ejecutó esta operación. Si está anidado dentro de un Nested Loop, este número puede ser mayor a 1.

Filter: (departamento_id = 10)

Filtro aplicado en el WHERE. Se ejecutó sobre cada fila.

Rows Removed by Filter: 97

Indica cuántas filas fueron descartadas por el filtro. Esto ayuda a entender el costo del WHERE.

Planning Time: 0.080 ms

Tiempo que tomó generar el plan de ejecución.

Execution Time: 0.045 ms

Tiempo real total de ejecución de la consulta.

🧠 ¿Qué métricas son clave para analizar?

 

Métrica

¿Por qué importa?

Tipo de escaneo

Si es Seq Scan, Index Scan o Bitmap Index, determina si se están aprovechando los índices.

Costo estimado

Ayuda a predecir si una consulta será costosa antes de ejecutarla.

Tiempo real vs estimado

Si hay mucha diferencia, pueden estar desactualizadas las estadísticas.

Rows Removed by Filter

Cuantas más filas descartadas, más trabajo innecesario realiza el sistema.

Loops

Muestra si hay operaciones repetitivas innecesarias.

🛠️ Mejores prácticas al usar EXPLAIN ANALYZE

Evitar usarlo en producción sobre consultas pesadas, ya que realmente ejecuta la instrucción.

Comparar estimaciones con resultados reales para detectar problemas de estadísticas.

Monitorear cambios tras agregar índices u optimizar JOINs.

 

🧪 Otro ejemplo con JOIN

EXPLAIN ANALYZE

SELECT e.nombre, d.nombre

FROM empleados e

JOIN departamentos d ON e.departamento_id = d.id

WHERE d.nombre = ‘Ventas’;

Posible resultado:

text

Nested Loop  (cost=0.43..8.52 rows=1 width=64) (actual time=0.030..0.032 rows=1 loops=1)

  ->  Index Scan using idx_departamentos_nombre on departamentos d  (cost=0.29..8.31 rows=1 width=32)

      (actual time=0.020..0.021 rows=1 loops=1)

        Index Cond: (nombre = ‘Ventas’)

  ->  Index Scan using idx_empleados_depto on empleados e  (cost=0.14..0.21 rows=1 width=32)

      (actual time=0.008..0.009 rows=1 loops=1)

        Index Cond: (departamento_id = d.id)

Planning Time: 0.350 ms

Execution Time: 0.060 ms

👉 Este plan muestra:

Uso de índices en ambas tablas

Nested Loop eficiente por la poca cantidad de datos

Tiempos de ejecución bajos

Planificación óptima

¿Por qué utilizar EXPLAIN?

El objetivo principal es optimizar el código SQL. A través de esta herramienta, se pueden:

Detectar cuellos de botella

Verificar si se están utilizando los índices correctamente

Ajustar estructuras de tablas o estadísticas

Identificar operaciones costosas (como Nested Loops, Hash Joins o Merge Joins)

Pros y Contras de Explain Plan en PostgreSQL vs SQL Server