

# Aurora DSQL EXPLAIN 계획의 일괄 중첩 루프 조인
<a name="batched-nested-loop-joins"></a>

쿼리가 Aurora DSQL이 스토리지에서 효율적으로 스캔할 수 있는 내부 입력에 작은 외부 입력을 조인하면 Aurora DSQL은 `Nested Loop (Batched Join)` 계획을 선택할 수 있습니다. 이 조인 유형은 내부를 탐색하기 전에 여러 외부 행을 그룹화하여 컴퓨팅 계층과 스토리지 계층 간의 왕복을 줄입니다.

표준 중첩 루프는 한 번에 하나의 외부 행을 처리하고 모든 행에 대해 내부 스캔을 다시 실행합니다. 일괄 중첩 루프 조인은 외부 행의 배치를 수집하고 전체 배치에 대한 내부 스캔 작업을 빌드한 다음 반환된 내부 행을 일치하는 외부 행에 다시 조인합니다.

## 일괄 중첩 루프 조인의 작동 방식
<a name="batched-nested-loop-joins-how-it-works"></a>

1. Aurora DSQL은 조인의 외부에서 행 배치를 읽습니다.

1. 내부 측이 외부 측에 `Index Cond` 파라미터가 지정된 `Index Scan` 또는 `Index Only Scan`인 경우 Aurora DSQL은 각 외부 행의 조건을 바인딩하고 결과 인덱스 스캔 키를 하나의 일괄 내부 스캔으로 결합합니다. 다른 조인 조건자는 내부 스캔을 구동하지 않습니다.

1. 외부 파라미터가 지정된 `Index Cond` 없는 `Index Scan` 또는 `Index Only Scan`은 `Full Scan` 또는 `Sequential Scan`처럼 동작합니다. Aurora DSQL에는 결합할 파라미터화된 인덱스 스캔 키가 없으며 외부 행당 하나의 내부 스캔 대신 외부 배치당 하나의 내부 스캔을 실행합니다.

1. Aurora DSQL은 배치를 위해 내부 측의 행이 도착하는 대로 이를 스트리밍합니다. 조인하기 전에 배치에 대한 전체 내부 결과를 구체화하지는 않습니다.

1. 내부 `Index Scan` 또는 `Index Only Scan`에 외부 파라미터가 지정된 `Index Cond`가 있는 경우 Aurora DSQL은 `Recheck Cond`를 사용하여 반환된 각 내부 행을 배치의 해당 외부 행과 다시 일치시킵니다. 그런 다음 Aurora DSQL은 나머지 조인 조건자를 적용합니다. 외부 파라미터화된 `Index Cond`가 없으면 Aurora DSQL은 외부 배치에 대해 스트리밍된 각 내부 행과 일치할 때 조인 조건자를 직접 적용합니다.

1. 왼쪽 및 안티 조인의 경우 Aurora DSQL은 일치하는 외부 행을 추적하고 배치에 대한 내부 스캔이 완료된 후 일치하지 않는 행을 내보냅니다.

이 접근 방식은 내부 측이 파라미터화된 `Index Cond`가 있는 인덱스 스캔인 경우에 가장 유용합니다. 결합된 스캔 키가 전체 외부 배치에 대한 대상 스토리지 액세스를 제공하기 때문입니다.

## Aurora DSQL에서 이 조인을 사용하는 경우
<a name="batched-nested-loop-joins-when-used"></a>

Aurora DSQL은 조인의 내부가 물리적 스캔 노드 즉, `Index Scan`, `Index Only Scan`, `Full Scan`, 또는 `Sequential Scan`이고, 외부 행마다 내부 스캔을 수행하는 것보다 일괄 처리 방식의 비용이 더 적게 들 것으로 예상되는 경우 일괄 중첩 루프 조인을 고려합니다. 실제로 가장 큰 이점은 일반적으로 더 작은 외부 입력과 외부에 `Index Cond` 파라미터가 지정된 내부 인덱스 스캔에서 비롯됩니다.

해시 조인 또는 병합 조인과 같이 다른 계획 형태가 더 저렴한 경우 Aurora DSQL은 대신 해당 계획을 선택합니다. 튜닝 중에 계획 형태를 비교하려면 현재 세션에 대해 일괄 중첩 루프 조인을 비활성화할 수 있습니다.

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

## 일괄 중첩 루프 조인 출력을 읽는 방법
<a name="batched-nested-loop-joins-reading-output"></a>

다음 쿼리는 [Aurora DSQL EXPLAIN 계획 읽기](reading-dsql-explain-plans.md)의 `transaction` 샘플 및 `account` 테이블을 사용합니다.

```
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;
```

EXPLAIN 계획에는 다음과 유사한 출력이 포함될 수 있습니다.

```
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)`  
Aurora DSQL이 조인의 내부 측을 탐색하기 전에 외부 행을 일괄 처리하고 있음을 보여줍니다.

`Index Cond`  
현재 배치의 내부 측을 프로브하는 데 사용되는 조건자를 표시합니다. 내부 측이 `Index Scan` 또는 `Index Only Scan`인 경우, 이 조건자는 조인의 외부 측에서 열을 참조하는 경우가 많습니다.

`Filter`  
조인 결과에 적용된 조건을 표시합니다. 이 예제에서는 `WHERE (a.status = 'active' OR a.customer_id IS NULL)` 조건이 여기에 나타납니다. 표준 SQL 왼쪽 조인 의미 체계에서는 이 조건을 내부 스캔으로 푸시할 수 없습니다. 이렇게 하면 쿼리 결과가 변경되기 때문입니다. Aurora DSQL은 조인 노드에 필터로 표시합니다. 반대로 `t.transaction_date`의 조건은 외부 테이블만 참조하므로 외부 물리적 스캔 아래에 나타납니다.

`Join Type`  
`Left`, `Semi` 또는 `Anti`와 같이 일괄 조인의 조인 의미 체계를 표시합니다.

`Recheck Cond`  
내부 측이 `Index Scan`이거나 조인의 외부 측에 `Index Cond` 파라미터가 하나 이상 있는 `Index Only Scan`인 경우에만 나타납니다. 반환된 각 내부 행에 대해 Aurora DSQL은 배치의 모든 외부 행에 대해 재점검을 실행하여 해당 프로브를 생성한 외부 행을 결정하고 해당 내부 행과 조인해야 하는 외부 행을 결정합니다.

`Join Filter`  
Aurora DSQL이 내부 행을 배치의 후보 외부 행과 다시 일치시킨 후 평가하는 조인 조건자를 표시합니다. 이러한 조건자는 조인하는 행 페어에 영향을 미치지만, `Index Cond`가 구동하는 방식으로 스토리지 프로브를 구동하지는 않습니다.

이전 정렬 노드  
쿼리에 정렬된 출력이 필요할 때 나타날 수 있습니다. 배치 중첩 루프 조인은 표준 중첩 루프와 동일한 출력 순서 보장을 유지하지 않으므로 Aurora DSQL은 최종 결과 세트를 반환하기 전에 명시적 정렬을 추가할 수 있습니다.