🐕 조인의 종류

RDBMS에서 조인은 단순히 두 개의 테이블을 연결하는 개념이 아닙니다. SQL Server는 내부적으로 다음과 같은 3가지 방식 중 하나로 조인을 수행합니다:

  1. Nested Loop (중첩 루프 조인)
  2. Merge Join (병합 조인)
  3. Hash Join (해시 조인)

각 방식은 데이터의 양, 정렬 여부, 인덱스 유무 등에 따라 선택되며, 옵티마이저가 자동으로 결정하거나 OPTION 힌트를 통해 강제할 수도 있습니다.


🧪 실습 환경 준비

사용 데이터베이스

  • BaseballData 데이터베이스를 사용합니다.
  • 주로 사용하는 테이블: players, salaries, teams

🪐 1. 세 가지 조인 방식 살펴보기

Merge Join (병합 조인)

SELECT *
FROM players AS p
	INNER JOIN salaries AS s
	ON p.playerID = s.playerID;
  • 정렬이 보장된 상태에서 사용하는 방식
  • 대량 데이터에 적합
  • 실행 계획에서 Merge Join으로 표시됨

Nested Loop 조인

SELECT TOP 5 *
FROM players AS p
	INNER JOIN salaries AS s
	ON p.playerID = s.playerID;
  • TOP 키워드 등으로 부분 범위 검색을 수행할 때 사용됨
  • 실행 계획에서 Nested Loops로 표시됨

Hash Join

SELECT *
FROM salaries AS s
	INNER JOIN teams AS t
	ON s.teamID = t.teamID;
  • 정렬이 없어도 가능
  • 대용량, 무작위 데이터 집합에 적합
  • 실행 계획에서 Hash Match로 표시됨

🧠 2. Nested Loop 조인의 동작 원리

NL 조인은 이름 그대로 중첩된 루프를 돌면서 외부 테이블의 한 행마다 내부 테이블을 탐색하는 방식입니다.

외부(OUTER) 테이블을 순차적으로 순회하며
내부(INNER) 테이블에 랜덤 액세스하는 방식입니다.

for (외부테이블의 row in TableA)
{
    for (내부테이블의 row in TableB)
    {
        if (rowA.key == rowB.key)
            조인 결과에 포함
    }
}
  • 시간 복잡도: O(N * M)
  • 성능: 작은 범위 or 결과 집합이 제한된 경우 매우 빠름
  • 내부 테이블에 인덱스가 없으면 성능 급락

🧪 3. C#으로 보는 Nested Loop 조인의 개념

NL 조인의 개념은 프로그래밍에서 이중 루프 구조와 동일합니다.

foreach (Player p in players)
{
    foreach (Salary s in salaries)
    {
        if (p.playerId == s.playerId)
        {
            result.Add(p.playerId);
            break;
        }
    }
}

✅ 개선 방법 - Dictionary 사용 (해시 탐색)

Dictionary<int, Salary> salariesDict = ...
foreach (Player p in players)
{
    if (salariesDict.TryGetValue(p.playerId, out var s))
    {
        result.Add(p.playerId);
    }
}
  • 내부 탐색을 List → Dictionary로 변경
  • 시간 복잡도: O(N)
  • 내부 테이블에 인덱스를 거는 것과 유사한 최적화 방식

🧪 4. SQL에서 Nested Loop 조인 해석하기

SELECT *
FROM players AS p
	INNER JOIN salaries AS s
	ON p.playerID = s.playerID
	OPTION(LOOP JOIN);

실행 계획 분석

  • salaries 테이블: Clustered Index Scan (외부 테이블)
  • players 테이블: Index Seek + Key Lookup (내부 테이블)
  • 이유: players에 인덱스가 존재 → 빠른 랜덤 액세스 가능

조인 순서 강제

SELECT *
FROM players AS p
	INNER JOIN salaries AS s
	ON p.playerID = s.playerID
	OPTION(FORCE ORDER, LOOP JOIN);
  • FORCE ORDER 힌트를 통해 FROM 절 순서 강제
  • 조인 순서와 실행 계획 제어 가능

🧪 5. 왜 TOP 5일 때 NL 조인이 사용될까?

SELECT TOP 5 *
FROM players AS p
	INNER JOIN salaries AS s
	ON p.playerID = s.playerID;
  • 결과의 개수가 제한되어 있기 때문에 NL 조인이 효과적
  • 조건을 만족하는 순간 바로 종료 가능 → 빠른 처리
  • C# 예제에서 if (result.Count >= 5) break; 와 동일

profile
李家네_공부방

0개의 댓글