Skip to content

Latest commit

 

History

History
133 lines (98 loc) · 8.87 KB

7. 조인의 원리.md

File metadata and controls

133 lines (98 loc) · 8.87 KB

조인의 원리

개요

조인의 수행 원리에 대해 알아봅시다.

핵심 용어

  • 중첩 루프 조인(Nested Loop Join): 중첩 for문과 같은 원리로 조건에 맞는 조인을 하는 방법
  • 정렬 병합 조인(Sorted Merge Join): 각각의 테이블을 조인할 필드 기준으로 정렬한 후 조인을 하는 방법
  • 해시 조인(Hash Join): 해시 테이블을 기반으로 조인하는 방법

중첩 루프 조인 (NLJ, Nested Loop Join)

image
  • 의미: 중첩 for 문과 같은 원리로 조건에 맞는 조인을 하는 방법
    • 반복문의 외부에 있는 테이블을 선행 테이블 또는 외부 테이블 (Outer Table)이라고 한다.
    • 반복문의 내부에 있는 테이블을 후행 테이블 또는 내부 테이블(Inner Table)이라고 한다.
  • 수행 과정

    1. 선행 테이블에서 조건을 만족하는 첫 번째 행을 스캔한다. 이 때, 선행 테이블에 주어진 조건을 만족하지 않는 경우 해당 데이터는 필터링 한다.
    2. 선행 테이블의 조인 키를 가지고 후행 테이블에 조인키가 존재하는지 스캔한다.
    3. 후행 테이블의 인덱스에 선행 테이블의 조인 키가 존재하는지 확인한다. 선행 테이블의 조인값이 후행 테이블에 존재하지 않으면 선행 테이블 데이터는 필터링 한다.
    4. 인덱스에서 추출한 레코드 식별자를 이용하여 후행 테이블을 액세스한다. 후행 테이블에 주어진 조건까지 모두 만족하면 해당 행을 추출버퍼에 넣는다.
  • 특징

    • 랜덤 접근에 대한 비용이 많이 증가하므로 대용량의 테이블에서는 사용하지 않는다.
    • 절차적이며, 프로그래밍에서 FOR, WHILE문과 같은 반복문 구조로 수행된다.
    • 선행테이블은 풀스캔하므로, 선행테이블의 크기가 작을수록 유리하다.
    • 후행테이블에 대해서는 반드시 인덱스가 존재해야 NLJ가 가능하다.
    • 인덱스 구성 전략에 따라 조인 효율이 크게 달라진다.
  • 블록 중첩 루프 조인(BNL, Block Nested Loop)

    • 중첩 루프 조인에서 발전한 형태이다.
    • 조인할 테이블을 작은 블록으로 나눠서 블록 하나씩으로 조인한다.

정렬 병합 조인

image
  • 의미: 각각의 테이블을 조인할 필드 기준으로 정렬하고, 정렬이 끝난 이후에 조인 작업을 수행하는 조인
  • 수행 과정

    1. 선행 테이블에서 주어진 조건을 만족하는 행을 찾는다.
    2. 선행 테이블의 조인 키를 기준으로 정렬작업을 수행한다.
    3. 1~2번 작업을 선행 테이블의 조건을 만족하는 모든 행에 대해 반복 수행한다.
    4. 후행 테이블에서 주어진 조건을 만족하는 행을 찾는다.
    5. 후행 테이블의 조인 키를 기준으로 정렬작업을 수행한다.
    6. 3~4번 작업을 후행 테이블의 조건을 만족하는 모든 행에 대해 반복 수행한다.
    7. 정렬된 결과를 이용하여 조인을 수행하며 조인에 성공하면 추출버퍼에 넣는다.
  • 특징

    • 인덱스가 없어도 가능한 조인 방법이다.
    • 대부분 해시 조인보다 느린 성능이지만, 아래와 같은 상황에서는 정렬 병합 조인이 유용하다.
      • First 테이블에 Sort 연산을 대체할 인덱스가 있을 때
      • 조인할 First 집합이 이미 정렬되어 있을 때
      • 조인 조건식이 등차(=) 조건이 아닐때
    • 두 테이블의 사이즈가 비슷한 경우유리하다.

해시 조인

image
  • 의미: 해시 테이블을 기반으로 조인하는 방법
  • 수행 과정

    1. 선행 테이블에서 주어진 조건을 만족하는 행을 찾는다.
    2. 선행 테이블의 조인키를 기준으로 해시함수를 적용하여 해시 테이블을 생성한다. 이때, 조인 컬럼과 SELECT 절에서 필요로 하는 컬럼도 함께 저장한다.
    3. 1~2번 작업을 선행 테이블의 조건을 만족하는 모든 행에 대해 반복 수행한다.
    4. 후행 테이블에서 주어진 조건을 만족하는 행을 찾는다.
    5. 후행 테이블의 조인키를 기준으로 해시 함수를 적용하여 해당 버킷을 찾는다.
    6. 조인에 성공하면 추출버퍼에 넣는다.
    7. 3~5번 작업을 후행 테이블의 조건을 만족하는 모든 행에 대해 반복 수행한다.
  • 특징

    • 조인 칼럼의 인덱스가 존재하지 않은 경우에도 사용할 수 있다.
    • 메모리 사용이 큰 대용량 테이블 조인 시 메모리 외에 임시영역까지 사용하여 저장할 수 있어 유리하다.
    • 두 개의 테이블을 조인한다고 했을 때, 하나의 테이블이 메모리에 온전히 들어간다면 보통 중첩 루프 조인보다 더 효율적이다.
    • 메모리에 올릴 수 없을 정도로 크다면 디스크를 사용하는 비용이 발생된다.
    • 동등(=) 조인에서만 사용할 수 있다.
    • MySQL8.0.18 릴리스와 함께 이 기능을 사용할 수 있게 되었다.

MySQL에서의 해시 조인 단계

  • 빌드 단계

    • 의미: 입력 테이블 중 하나를 기반으로 메모리 내 해시 테이블을 빌드하는 단계
    • ex) persons와 countries라는 테이블을 조인한다고 했을 때 둘 중 더 작은 바이트의 테이블을 기반으로 해시 테이블을 빌드한다. 조인에 사용되는 필드인 'countries.country_id'가 해시 테이블의 키로 사용된다.
  • 프로브 단계

    • 의미: 레코드 읽기를 시작하며 각 레코드에서 해시 테이블의 키와 일치하는 레코드를 찾아서 결괏값으로 반환하는 단계
      • 각 테이블은 한 번씩만 읽게 되어 중첩 루프 조인보다 보통 성능이 더 뛰어나다.
      • 참고: 사용 가능한 메모리양은 시스템 변수 join_buffer_size에 의해 제어되며, 런타임 시에 조정할 수 있다.
    • ex) 각 레코드에서 'persons.country_id'에 일치하는 레코드를 찾아서 결괏값으로 반환한다.

레퍼런스