View a markdown version of this page

Junções de loop aninhado em lote nos planos EXPLAIN do Aurora DSQL - Amazon Aurora DSQL

Junções de loop aninhado em lote nos planos EXPLAIN do Aurora DSQL

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

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

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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

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 consulta a seguir usa as tabelas de exemplo transaction e account de Ler os planos EXPLAIN do Aurora DSQL:

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.