NL(Nested Loop) 조인은 중첩 반복 조인이라고도 하며, 데이터베이스에서 가장 기본적인 조인 알고리즘 방식이다. 두 개의 테이블을 조인할 때 한 테이블의 모든 행을 기준으로 다른 테이블의 행을 순차적으로 검색하면서 조인하는 방식이다.
즉, for문과 비슷하게 동작한다고 생각하면 된다.
아래와 같은 구조의 이중포문을 보았을 때, i=0 일때 j는 0,1,2,3,4 와 같은 식으로 5번 반복한다. 바깥 for문 한번에 안쪽 포문 5번 반복하는 것이다.
for(i =0 i<5 i++) {
for(j=0 j<5 j++)
...
}
NL조인도 이와 동일하다. 아래의 쿼리에서 선행 테이블인 사원 테이블이 바깥 for문, 고객 테이블이 안쪽 for문이라고 생각하면 된다.
SELECT E.사원명, C.고객명, C.전화번호
FROM 사원 E, -- OUTER (드라이빙 테이블)
고객 C -- INNER
WHERE E.입사일자 >= '19960101'
AND C.관리사원번호 = E.사원번호
예를 들어, E.입사일자 >= '19960101' 조건을 만족하는 사원이 2명이라고 가정해보자. 이 경우 NL 조인은 각 사원에 대해 고객 테이블을 스캔하게 된다.
만약 고객 테이블에 100명의 데이터가 있다면, "C.관리사원번호 = E.사원번호" 조건을 확인하기 위해 사원 한 명당 100번의 스캔이 필요하다. 결국 2명의 사원에 대해 총 200번의 스캔이 발생하게 되는 것이다.
이는 아래의 이중 for문과 같은 방식으로 동작한다:
for(i =0 i<1 i++) {
for(j=0 j<99 j++)
...
}
하지만, 이러한 방식은 비효율적이다. OUTER와 INNER의 크기가 커질 수록 스캔 횟수가 많아지고, 그만큼 비용이 많이 나오기 때문이다. 그래서, NL조인은 적절한 인덱스가 생성되어있어야한다.
일반적으로 NL조인은 Outer와 Inner 양쪽 테이블 모두 인덱스를 이용한다. Outer쪽 테이블은 사이즈가 크지 않으면 인덱스를 이용하지 않을 수 있다. Table을 Full Scan 하더라도 한 번에 그치기 때문이다.
반면, Inner쪽 테이블은 인덱스를 사용해야 한다. 인덱스를 사용하지 않으면 Outer 루프에서 읽은 건수만큼 Table Full Scan을 반복하기 때문이다.
결국 NL 조인은 "인덱스를 이용한 조인 방식" 이라고 할 수 있다. 위 예제에서는 Inner 테이블인 고객 테이블의 관리사원번호 컬럼에 인덱스가 있어야 한다. 인덱스가 없다면 사원 한 명당 고객 테이블을 Full Scan 하게 되어 성능이 매우 저하될 것이다. 반면, 인덱스가 있다면 각 사원번호에 해당하는 고객을 인덱스를 통해 빠르게 찾을 수 있다. Outer 테이블인 사원 테이블의 입사일자 컬럼에도 인덱스가 있으면 좋지만, 테이블 크기가 작다면 Full Scan이 오히려 유리할 수 있다.
또한 NL 조인은 Random 액세스 위주의 조인 방식이다. 따라서 인덱스가 잘 구성되어 있더라도 대량의 데이터를 조인할 때는 효율성이 떨어질 수 있다. 이러한 특징들을 고려할 때, NL 조인은 소량의 데이터를 처리하거나 부분범위처리가 가능한 온라인 트랜잭션 환경에 가장 적합한 조인 방식이라고 할 수 있다.
참고
'Databases' 카테고리의 다른 글
데이터베이스 동시성 제어: 2PL (0) | 2025.02.22 |
---|---|
수직적 탐색 수평적 탐색 (0) | 2025.02.21 |
DELETE vs TRUNCATE (0) | 2025.02.03 |
바인드 변수를 사용하는 이유 (0) | 2025.01.12 |
뷰(View)의 개념과 뷰(View)를 사용해야 하는 이유 (2) | 2024.12.06 |