CodeGym /Cursos /SQL SELF /Conceptos básicos del plan de ejecución de consultas:

Conceptos básicos del plan de ejecución de consultas: cost, rows, width

SQL SELF
Nivel 41 , Lección 1
Disponible

Cuando escribes una consulta SQL, PostgreSQL no la ejecuta de inmediato. Primero pone en marcha su "cerebro" — el optimizador de consultas, que crea el plan de ejecución. Ese plan es como una ruta en un mapa: PostgreSQL calcula qué acciones y en qué orden debe hacer para conseguir los datos con éxito.

El optimizador de consultas evalúa todos los caminos posibles para ejecutar tu consulta: escaneo secuencial de la tabla, uso de índices, aplicar filtros y ordenamientos, etc. Intenta encontrar la forma más barata (en cuanto a recursos) de ejecutar tu consulta. O sea, busca un equilibrio entre el tiempo de ejecución y los recursos del servidor.

Parámetros clave del plan de ejecución

Bueno, ahora vamos a la "chicha" — analizar los parámetros que PostgreSQL te muestra cuando ejecutas el comando EXPLAIN. Para empezar, veamos un ejemplo sencillo:

EXPLAIN
SELECT * FROM students WHERE age > 20;

Vas a ver algo parecido a esto:

Seq Scan on students  (cost=0.00..35.00 rows=7 width=72)
  Filter: (age > 20)

Vamos a desmenuzar esas palabras y números misteriosos.

1. cost (coste de ejecución)

cost — es una estimación de cuántos recursos se necesitan para ejecutar la consulta. Este parámetro tiene dos partes:

  • Startup Cost: coste de arrancar la operación (por ejemplo, preparar el índice).
  • Total Cost: coste total de ejecutar toda la operación.

Ejemplo:

cost=0.00..35.00
  • 0.00 — es el Startup Cost.
  • 35.00 — es el Total Cost.

Cuanto más bajo sea el valor de cost, más preferible es ese plan para PostgreSQL. Pero ojo, cost es un valor relativo. No se mide en segundos ni milisegundos, sino que refleja una valoración interna de PostgreSQL.

2. rows (número estimado de filas)

rows muestra cuántas filas espera PostgreSQL devolver o procesar en esa etapa de la consulta. En nuestro ejemplo:

rows=7

Esto significa que PostgreSQL cree que el filtro age > 20 devolverá 7 filas. Estos datos vienen de las estadísticas que PostgreSQL recoge sobre la tabla. Si las estadísticas están desactualizadas, la predicción puede estar mal. Eso puede llevar a un plan menos óptimo.

3. width (ancho de la fila en bytes)

width — es el tamaño medio de cada fila devuelta en esa etapa, medido en bytes. En nuestro ejemplo:

width=72

Esto significa que cada fila devuelta ocupa de media 72 bytes. width tiene en cuenta el tamaño de los datos en las columnas y cualquier sobrecarga adicional, como identificadores de fila o información interna.

Es como cuando cargas una app. Si su "peso" (el equivalente a width) es grande, vas a tardar más en cargarla, aunque tengas internet rápido (el equivalente a cost).

Ejemplo de análisis de un plan de ejecución

Vamos a ver un ejemplo real. Supón que tienes una tabla students:

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    age INTEGER,
    major VARCHAR(50)
);

Y ejecutamos la siguiente consulta:

EXPLAIN
SELECT * FROM students WHERE age > 20 AND major = 'CS';

El resultado puede ser así:

Seq Scan on students  (cost=0.00..42.50 rows=3 width=164)
  Filter: ((age > 20) AND (major = 'CS'))
  • Seq Scan: PostgreSQL hace un escaneo secuencial de la tabla students. O sea, recorre todas las filas una a una.
  • cost=0.00..42.50: Coste de ejecutar la operación. Startup Cost es 0.00 y el coste total es 42.50.
  • rows=3: PostgreSQL espera que el filtro age > 20 AND major = 'CS' devuelva 3 filas.
  • width=164: Cada fila ocupa de media 164 bytes.

Ahora ya entiendes cómo PostgreSQL toma decisiones y puedes detectar puntos débiles en tus consultas. Por ejemplo, si ves un cost alto, puede ser señal de que la consulta es demasiado pesada. O si ves muchas filas en rows, deberías revisar tu filtro.

¿Cómo funciona cost en la práctica?

Vamos a añadir un índice en la columna age:

CREATE INDEX idx_age ON students(age);

Ahora repetimos la consulta:

EXPLAIN
SELECT * FROM students WHERE age > 20 AND major = 'CS';

El resultado puede cambiar:

Bitmap Heap Scan on students  (cost=4.37..20.50 rows=3 width=164)
  Recheck Cond: (age > 20)
  Filter: (major = 'CS')
  ->  Bitmap Index Scan on idx_age  (cost=0.00..4.37 rows=20 width=0)
        Index Cond: (age > 20)

¿Qué ha cambiado?

  • En vez de Seq Scan ahora se usa Bitmap Heap Scan: PostgreSQL primero busca las filas que cumplen la condición en el índice idx_age y luego las saca de la tabla.
  • El cost ha bajado bastante: ahora el Startup Cost es 4.37 y el Total Cost es 20.50.
  • La operación es más eficiente gracias al índice.

Visualización: diferencia entre Seq Scan e Index Scan

Aquí tienes una pequeña tabla comparativa para que lo veas más claro:

Operación Introducción Ejemplo
Seq Scan Lee toda la tabla Recorre todas las filas una a una
Index Scan Usa un índice Selección rápida de filas usando el índice

Trampas y errores típicos

Cuando uses los parámetros del plan de ejecución, prepárate para algunas sorpresas. Por ejemplo, no siempre un cost bajo significa mejor ejecución. Si las estadísticas de la base de datos están desactualizadas (por ejemplo, después de actualizar muchas filas en la tabla), el plan puede no ser muy preciso. Actualiza las estadísticas con el comando ANALYZE. Más sobre esto en la próxima lección.

Asegúrate de usar índices donde realmente los necesitas. Pero tampoco abuses de ellos: ocupan espacio y pueden ralentizar las operaciones de escritura.

2
Tarea
SQL SELF, nivel 41, lección 1
Bloqueada
Análisis del plan de ejecución `EXPLAIN` con escaneo secuencial
Análisis del plan de ejecución `EXPLAIN` con escaneo secuencial
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION