¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Leer un plan de consulta con EXPLAIN

Después de esta lección: Puedo leer un plan con EXPLAIN y explicar por qué una consulta cuesta menos que otra.

Lección de 60 minSin comandos

Qué muestra EXPLAIN

EXPLAIN muestra el plan de una consulta: los pasos que DuckDB sigue para contestarla, de abajo arriba. Leerlo te dice qué tabla se recorre, qué filtros se aplican y dónde se agrupa.

Una consulta lenta casi nunca se arregla a ciegas. Primero se mira el plan y se ve qué paso trabaja con más filas.

Al terminar esta lección

Nota

Puedo leer un plan con EXPLAIN y explicar por qué una consulta cuesta menos que otra.

Palabras clave

PalabraQué significaEjemplo
Plan de consultalos pasos con que el motor contesta una consulta
EXPLAINla palabra que pide el plan en vez del resultado
Escaneoun paso que lee una tabla enteraSeq Scan
Filtroun paso que descarta las filas que no cumplen la condición
Filas estimadaslas filas que el motor calcula que pasarán por un paso~10 rows

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

EXPLAIN muestra los pasos de la consulta

Escribe EXPLAIN delante de una consulta. No la ejecuta: devuelve el plan, un árbol de pasos. Se lee de abajo arriba. Abajo se leen las tablas y arriba sale el resultado.

Cada paso tiene un nombre. Seq Scan lee una tabla, Hash Join une dos y Hash Group By agrupa. Bajo cada nombre aparecen las columnas que usa y, tras un ~, las filas que el motor espera.

Ejemplo resuelto: los pasos de un plan

OrdenPasoQué haceQué se ve en él
1Seq Scan de ridesLee viajes: solo station_id y minutesFilters: minutes > 20
2Seq Scan de stationsLee estaciones: solo station_id y nameUna condición que DuckDB añade solo
3Hash JoinUne los viajes con las estacionesstation_id = station_id
4Hash Group ByAgrupa por name y suma minutesAggregates: sum(minutes)

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Pruébalo: el plan de una suma

Código: duckdb
-- El plan de una suma sobre una sola columna.
explain select sum(minutes) from rides;
-- Cambia sum(minutes) por * y mira las columnas que lee el escaneo.

Cuanto menos lee un escaneo, menos cuesta

En la lección 1 viste que una tabla por columnas lee solo las columnas que nombras. El plan lo confirma: el Seq Scan lista las columnas que va a leer.

Una suma de minutes lee una columna. Un select * lee las cuatro. El dibujo cambia con la versión y con las estadísticas, así que fíjate en los nombres de los pasos y no en cada línea.

Ejemplo resuelto: columnas que lee el escaneo

ConsultaColumnas que lista el Seq Scan
select sum(minutes) from ridesminutes
select * from ridesride_id, station_id, minutes, paid_eur

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Pruébalo: el plan de un join

Código: duckdb
-- El plan de un join con un filtro, que se escribe después.
explain
select name, sum(minutes) as total
from rides join stations using (station_id)
where minutes > 20
group by name;
-- Busca los pasos Seq Scan, Hash Join y Hash Group By.

Filtrar antes de unir reduce el trabajo

Un filtro antes de un JOIN hace que se unan menos filas. DuckDB suele mover los filtros hacia abajo por su cuenta. En el plan anterior, minutes > 20 aparece dentro del escaneo de rides, aunque se escribió en el WHERE.

Pero filtrar antes no siempre da lo mismo. Con un LEFT JOIN, un WHERE sobre la tabla de la derecha borra las filas sin pareja.

Ejemplo resuelto: dos formas de filtrar

namelong_rides con WHERElong_rides con el filtro antes
Estación Norte11
Parque Central11
Plaza Mayor11
Puertono aparece0
Universidad22

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un error frecuente

Advertencia

Mucha gente cree que mover una condición entre WHERE y una subconsulta siempre da el mismo resultado. Con LEFT JOIN no es así: un WHERE sobre la tabla derecha descarta las estaciones sin viajes. Si quieres conservarlas, filtra antes de unir.

Pruébalo: filtrar antes de unir

Código: duckdb
-- Primero se filtran los viajes; después se unen a las estaciones.
select s.name, count(r.ride_id) as long_rides
from stations as s
left join (select * from rides where minutes > 20) as r
  on r.station_id = s.station_id
group by s.name
order by s.name;
-- Mueve la condición a un WHERE de fuera y mira qué fila desaparece.

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.