

# Uniones de bucles anidados por lotes en los planes EXPLAIN de Aurora DSQL
<a name="batched-nested-loop-joins"></a>

Cuando una consulta une una entrada externa pequeña con una entrada interna que Aurora DSQL puede escanear eficientemente desde el almacenamiento, Aurora DSQL puede elegir un plan `Nested Loop (Batched Join)`. Este tipo de unión reduce los viajes de ida y vuelta entre las capas de procesamiento y almacenamiento, ya que agrupa varias filas externas antes de sondear la parte interna.

Un bucle anidado estándar procesa una fila externa a la vez y vuelve a ejecutar el escaneo interno para cada fila. Una unión de bucles anidados por lotes recopila un lote de filas externas, crea el trabajo de escaneo interno para todo el lote y, a continuación, une las filas internas devueltas con las filas externas correspondientes.

## Cómo funcionan las uniones de bucles anidados por lotes
<a name="batched-nested-loop-joins-how-it-works"></a>

1. Aurora DSQL lee un lote de filas del lado externo de la unión.

1. Si la parte interna es un `Index Scan` o `Index Only Scan` con un `Index Cond` parametrizado en la parte externa, Aurora DSQL vincula la condición para cada fila externa y combina las claves de escaneo de índice resultantes en un escaneo interno por lotes. Otros predicados de unión no controlan el escaneo interno.

1. Una `Index Scan` o `Index Only Scan` sin una `Index Cond` con parámetros externos se comporta como una `Full Scan` o `Sequential Scan`. Aurora DSQL no tiene claves de escaneo de índice parametrizadas para combinar y ejecuta un escaneo interno por lote externo en lugar de un escaneo interno por fila externa.

1. Aurora DSQL transmite las filas desde la parte interna a medida que llegan al lote. No materializa todo el resultado interno del lote antes de unirlo.

1. Cuando la `Index Scan` o `Index Only Scan` interna tiene una `Index Cond` con parámetros externos, Aurora DSQL utiliza la `Recheck Cond` para hacer coincidir cada fila interna devuelta con las filas externas aplicables del lote. A continuación, Aurora DSQL aplica los predicados de unión restantes. Sin una `Index Cond` con parámetros externos, Aurora DSQL aplica los predicados de unión directamente a medida que hace coincidir cada fila interna transmitida con el lote externo.

1. Para las uniones izquierdas y antiuniones, Aurora DSQL rastrea qué filas externas coinciden y emite las filas no coincidentes una vez finalizado el escaneo interno del lote.

Este enfoque resulta especialmente útil cuando la parte interna es un escaneo de índice con una `Index Cond` parametrizada, ya que las claves de escaneo combinadas proporcionan un acceso de almacenamiento específico para todo el lote externo.

## Cuando Aurora DSQL usa esta unión
<a name="batched-nested-loop-joins-when-used"></a>

Aurora DSQL considera las uniones de bucles anidados por lotes cuando la parte interior de la unión es un nodo de escaneo físico, es decir, `Index Scan`, `Index Only Scan`, `Full Scan` o `Sequential Scan`, y se espera que el procesamiento por lotes cueste menos que ejecutar el escaneo interno para cada fila exterior. En la práctica, el mayor beneficio suele consistir en una entrada exterior más pequeña y un escaneo de índice interior con una `Index Cond` parametrizada en la parte exterior.

Si otra forma de plan es más económica, como una unión hash o una unión de combinación, Aurora DSQL elige ese plan en su lugar. Para comparar formas de plan durante el ajuste, puede desactivar las uniones de bucles anidados por lotes para la sesión actual:

```
SET dsql.enable_batched_nestloop = off;
```

## Cómo leer el resultado de una unión de bucles anidados por lotes
<a name="batched-nested-loop-joins-reading-output"></a>

La siguiente consulta utiliza las tablas de ejemplo `transaction` y `account` de [Lectura de los planes EXPLAIN de Aurora DSQL](reading-dsql-explain-plans.md):

```
EXPLAIN
SELECT t.account_id, a.balance
FROM transaction t
LEFT JOIN account a
  ON t.account_id = a.customer_id
 AND a.balance > CASE
                    WHEN t.description LIKE 'fee%' THEN 0
                    ELSE 100
                  END
WHERE t.transaction_date >= '2025-01-01'
  AND (a.status = 'active' OR a.customer_id IS NULL)
ORDER BY t.account_id;
```

Un plan EXPLAIN puede incluir un resultado similar al siguiente:

```
Sort
  Sort Key: t.account_id
  -> Nested Loop (Batched Join)
       Filter: (((status)::text = 'active'::text) OR (customer_id IS NULL))
       Join Type: Left
       Recheck Cond: (customer_id = t.account_id)
       Join Filter: (balance > CASE WHEN (t.description ~~ 'fee%'::text) THEN '0'::numeric ELSE '100'::numeric END)
       -> Full Scan (btree-table) on transaction t
            -> Storage Scan on transaction t
                 Filters: (transaction_date >= '2025-01-01 00:00:00'::timestamp without time zone)
                 -> B-Tree Scan on transaction t
       -> Index Only Scan using idx1 on account a
            Index Cond: (customer_id = t.account_id)
```

`Nested Loop (Batched Join)`  
Muestra que Aurora DSQL está agrupando por lotes las filas externas antes de sondear la parte interna de la unión.

`Index Cond`  
Muestra el predicado utilizado para sondear el lado interno del lote actual. Cuando el lado interior es un `Index Scan` o `Index Only Scan`, este predicado suele hacer referencia a las columnas de la parte exterior de la unión.

`Filter`  
Muestra una condición aplicada al resultado de la unión. En este ejemplo, la condición `WHERE (a.status = 'active' OR a.customer_id IS NULL)` aparece aquí. Según la semántica estándar de combinación izquierda de SQL, esta condición no se puede incluir en el análisis interno porque, al hacerlo, se cambiarían los resultados de la consulta. Aurora DSQL lo muestra como un filtro en el nodo de unión. Por el contrario, la condición en `t.transaction_date` hace referencia solo a la tabla exterior, por lo que aparece en el escaneo físico externo.

`Join Type`  
Muestra la semántica de la unión por lotes, como `Left`, `Semi` o `Anti`.

`Recheck Cond`  
Solo aparece cuando la parte interior es una `Index Scan` o `Index Only Scan` con al menos una `Index Cond` parametrizada en el lado exterior de la unión. Para cada fila interior devuelta, Aurora DSQL vuelve a realizar la comprobación con todas las filas exteriores del lote para determinar qué filas exteriores produjeron esa sonda y deberían unirse a esa fila interior.

`Join Filter`  
Muestra los predicados de unión que Aurora DSQL evalúa después de hacer coincidir una fila interior con las filas exteriores candidatas del lote. Estos predicados afectan a los pares de filas que se unen, pero no controlan la sonda de almacenamiento como lo hace `Index Cond`.

Un nodo de ordenación anterior  
Puede aparecer cuando la consulta necesita una salida ordenada. Las uniones de bucles anidados por lotes no conservan las mismas garantías de orden de salida que un bucle anidado estándar, por lo que Aurora DSQL puede agregar una ordenación explícita antes de devolver el conjunto de resultados final.