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
-
O Aurora DSQL lê um lote de linhas do lado externo da junção.
-
Se o lado interno for um
Index ScanouIndex Only Scancom umIndex Condparametrizado 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. -
Um
Index ScanouIndex Only Scansem umIndex Condparametrizado pelo lado externo funciona como umFull ScanouSequential 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. -
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.
-
Quando o
Index ScanouIndex Only Scaninterno tem umIndex Condparametrizado pelo lado externo, o Aurora DSQL usa oRecheck Condpara 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 umIndex Condparametrizado 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. -
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 ScanouIndex 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 emt.transaction_datefaz 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,SemiouAnti. Recheck Cond-
Aparece somente quando o lado interno é um
Index ScanouIndex Only Scancom pelo menos umIndex Condparametrizado 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 Condfaz. - 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.