

# Junções de loop aninhado em lote nos planos EXPLAIN do Aurora DSQL
<a name="batched-nested-loop-joins"></a>

Quando uma consulta faz a junção de uma entrada externa pequena com uma entrada interna que o Aurora DSQL pode examinar com eficiência a partir do armazenamento, o Aurora DSQL pode escolher um plano `Nested Loop (Batched Join)`. Esse tipo de junção reduz as viagens de ida e volta entre as camadas de computação e armazenamento ao agrupar várias linhas externas antes de consultar o lado interno.

Um loop aninhado padrão processa uma linha externa por vez e executa novamente a verificação interna para cada linha. Uma junção de loop aninhado em lote coleta um lote de linhas externas, cria o trabalho de verificação interna para todo o lote e, em seguida, faz a junção das linhas internas retornadas novamente com as linhas externas correspondentes.

## Como funcionam as junções de loop aninhado em lote
<a name="batched-nested-loop-joins-how-it-works"></a>

1. O Aurora DSQL lê um lote de linhas do lado externo da junção.

1. Se o lado interno for um `Index Scan` ou `Index Only Scan` com um `Index Cond` parametrizado na lateral externa, o Aurora DSQL associa a condição a cada linha externa e combina as chaves de verificação do índice resultantes em uma única verificação interna em lote. Outros predicados de junção não determinam a varredura interna.

1. Um `Index Scan` ou `Index Only Scan` sem um `Index Cond` parametrizado pelo lado externo funciona como um `Full Scan` ou `Sequential Scan`. O Aurora DSQL não tem chaves de varredura de índice parametrizadas para combinar e executa uma varredura interna por lote externo, em vez de uma varredura interna por linha externa.

1. O Aurora DSQL transmite as linhas do lado interno à medida que elas chegam para o lote. Ele não materializa todo o resultado interno do lote antes de realizar a junção.

1. Quando o `Index Scan` ou `Index Only Scan` interno tem um `Index Cond` parametrizado pelo lado externo, o Aurora DSQL usa o `Recheck Cond` para fazer a correspondência de cada linha interna retornada com as linhas externas aplicáveis do lote. Em seguida, o Aurora DSQL aplica os predicados de junção restantes. Sem um `Index Cond` parametrizado pelo lado externo, o Aurora DSQL aplica os predicados de junção diretamente ao fazer a correspondência de cada linha interna transmitida com o lote externo.

1. Para junções à esquerda e antijunções, o Aurora DSQL registra quais linhas externas tiveram correspondência e gera as linhas sem correspondência depois que a varredura interna do lote é concluída.

Essa abordagem é mais útil quando o lado interno é uma varredura de índice com um `Index Cond` parametrizado, porque as chaves de varredura combinadas fornecem acesso direcionado ao armazenamento para todo o lote externo.

## Quando o Aurora DSQL usa essa junção
<a name="batched-nested-loop-joins-when-used"></a>

O Aurora DSQL considera junções de loop aninhado em lote quando o lado interno da junção é um nó de varredura física, ou seja, um `Index Scan`, `Index Only Scan`, `Full Scan` ou `Sequential Scan`, e quando se espera que o uso de lotes tenha um custo menor do que executar a varredura interna para cada linha externa. Na prática, o maior benefício geralmente ocorre com uma entrada externa menor e uma varredura de índice interna com um `Index Cond` parametrizado pelo lado externo.

Se outra forma de plano for mais econômica, como uma junção hash ou uma junção merge, o Aurora DSQL escolherá esse plano. Para comparar as formas de plano durante o ajuste, é possível desabilitar as junções de loop aninhado em lote para a sessão atual:

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

## Como ler a saída de uma junção de loop aninhado em lote
<a name="batched-nested-loop-joins-reading-output"></a>

A consulta a seguir usa as tabelas de exemplo `transaction` e `account` de [Ler os planos EXPLAIN do 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;
```

Um plano EXPLAIN pode incluir uma saída semelhante à seguinte:

```
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)`  
Indica que o Aurora DSQL está agrupando as linhas externas em lotes antes de consultar o lado interno da junção.

`Index Cond`  
Mostra o predicado usado para consultar o lado interno no lote atual. Quando o lado interno é um `Index Scan` ou `Index Only Scan`, esse predicado geralmente faz referência a colunas do lado externo da junção.

`Filter`  
Mostra uma condição aplicada ao resultado da junção. Neste exemplo, a condição `WHERE (a.status = 'active' OR a.customer_id IS NULL)` aparece aqui. De acordo com a semântica de junção à esquerda do SQL padrão, essa condição não pode ser transferida para a varredura interna, pois isso alteraria os resultados da consulta. O Aurora DSQL a exibe como um filtro no nó de junção. Por outro lado, a condição em `t.transaction_date` faz referência somente à tabela externa, portanto aparece no nó de varredura física externa.

`Join Type`  
Mostra a semântica da junção em lote, como `Left`, `Semi` ou `Anti`.

`Recheck Cond`  
Aparece somente quando o lado interno é um `Index Scan` ou `Index Only Scan` com pelo menos um `Index Cond` parametrizado pelo lado externo da junção. Para cada linha interna retornada, o Aurora DSQL executa a reverificação em cada linha externa do lote para determinar quais linhas externas produziram essa consulta e devem ser associadas a essa linha interna.

`Join Filter`  
Mostra os predicados de junção que o Aurora DSQL avalia depois de fazer a correspondência de uma linha interna com as linhas externas candidatas no lote. Esses predicados afetam quais pares de linhas são associados, mas não determinam a consulta ao armazenamento da mesma forma que `Index Cond` faz.

Um nó de classificação anterior  
Pode aparecer quando a consulta exige uma saída ordenada. As junções de loop aninhado em lote não preservam as mesmas garantias de ordem de saída de um loop aninhado padrão; portanto, o Aurora DSQL pode adicionar uma classificação explícita antes de retornar o conjunto de resultados final.