CSㅣ조인(join)의 종류와 원리

휘Bin·2024년 1월 13일
0
post-thumbnail

조인의 종류

조인의 종류

'조인(join)'이란, 하나의 테이블이 아닌, 2개 이상의 테이블을 묶어 하나의 결과물을 만드는 것을 뜻한다. MySQL은 JOIN이라는 쿼리로, MongoDB에서는 lookup이라는 쿼리로 조인을 처리한다.

하지만 MongoDBa를 사용할 때는 lookup 사용을 비추천한다. MongoDB는 조인연산(lookup)에 대해 관계형 데이터베이스보다 성능이 떨어진다고 여러 벤치마크 테스트에서 알려져있다.

따라서 여러 테이블을 조인하는 작업이 많을 경우, MongoDB보다는 관계형 데이터베이스를 쓰는 것이 좋다.

조인의 종류에는 대표적으로 내부 조인, 왼쪽 조인, 오른쪽 조인, 합집합 조인이 있다.
그림으로 나타내면 아래와 같다.

간단하게 설명하면,

  • 내부 조인(inner join) : 왼쪽 테이블과 오른쪽 테이블의 두 행이 모두 일치하는 행이 있는 부분만 표기

  • 왼쪽 조인(left outer join) : 왼쪽 테이블의 모든 행이 결과 테이블에 표기

  • 오른쪽 조인(right outer join) : 오른쪽 테이블의 모든 행이 결과 테이블에 표기

  • 합집합 조인(full outer join) : 2개의 테이블을 기반으로 조인 조건에 만족하지 않는 행까지 모두 표기

SQL의 JOIN을 시각화해서 볼 수 있는 사이트가 있는 아래와 같다.

https://sql-joins.leopard.in.ua/

내부 조인

내부 조인은 두 테이블 간에 교집합을 나타낸다
예시로는 아래와 같다.

SELECT * FROM TableA A
INNER JOIN TableB B ON
A.key = B.key

왼쪽 조인

왼쪽 조인은, 테이블B의 일치하는 부분의 레코드와 함께 테이블A를 기준으로 완전한 레코드 집합을 생성한다. 만약 테이블B에 일치하는 항목이 없으면 해당 값은 null값.

SELECT * FROM TableA A
LEFT JOIN TableB B ON
A.key = B.key

오른쪽 조인

오른쪽 조인은, 테이블A에서 일치하는 부분의 레코드와 함께 테이블B를 기준으로 완전한 레코드 집합을 생성한다. 만약 테이블A에 일치하는 항목이 없으면 해당 값은 null값이 된다.

SELECT * FROM TableA A
RIGHT JOIN TableB B ON
A.key = B.key

합집합 조인

합집합 조인(완전 외부 조인)은, 양쪽 테이블에서 일치하는 레코드와 함께 테이블A와 테이블B의 모든 레코드 집합을 생성한다. 이때 일치하는 항목이 없으면 누락된 쪽에 null값이 포함되어 출력된다.

SELECT * FROM TableA A
FULL OUTER JOIN TableB B ON
A.key = B.key

조인의 원리

조인의 원리

조인은 조인의 기반으로 조인 작업이 이뤄진다.
조인의 원리에는 중첩 루프 조인, 정렬 병합 조인, 해시 조인이 있다.

중첩 루프 조인

'중첩 루프 조인(NLF, Nested Loop Join)'은, 중첩 for문과 같은 원리로, 조건에 맞는 조인을 하는 방법이고, 랜덤 접근에 대한 비용이 많이 증가하므로 대용량의 테이블에서는 사용하지 않는다.

만약 "c1,c2 테이블을 조인"했을 때, t1 테이블에서 행을 한 번에 하나씩 읽고, c2테이블에서도 행을 하나씩 읽어, 조건에 맞는 레코드를 찾아 결과값을 반환한다.
예시로는 아래와 같다.

for each row in c1 matching reference key{
	for each row in c2 matching reference key{
    	if row satisfies join conditions, send to client
    }
}

중첩 루프 조인에서 발전해, 조인할 테이블을 작은 블록으로 나눠 블록 하나씩 조인하는 '블록 중첩 루프 조인(BNL, Block Nested Loop)' 방식도 있다.

정렬 병합 조인

'정렬 병합 조인'이란, 각각의 테이블을 조인할 필드 기준으로 정렬하고, 정렬이 끝난 이후에 조인 작업을 수행하는 조인이다. 조인할 때 쓸 적절한 인덱스가 없고, 대용량의 테이블들을 조인하고 조인조건으로 <, > 등 범위 비교 연산자가 있을 때 쓴다.

해시 조인

해시 조인은, 해시 테이블을 기반으로 조인하는 방법이다. 2개의 테이블을 조인한다고 할 때, 하나의 테이블이 메모리에 온전히 들어간다면 보통 중첩 루프 조인보다 더 효율적이다(메모리에 올릴 수 없을 정도로 크다면 디스크 사용 비용이 발생). 또한, 동등(=)조인에서만 사용할 수 있다.

MySQL의 예시로, MySQL의 해시 조인 단계빌드 단계, 프로브 단계로 나뉘는데 설명해보면 아래와 같다.

빌드 단계

빌드 단계는, 입력 테이블 중 하나를 기반으로 메모리 내 해시 테이블을 빌드하는 단계이다.

velog와 hwibin테이블을 조인한다고 할 때, 둘 중에 바이트가 더 작은 테이블을 기반으로 테이블을 빌드한다.

또한, 조인에 사용되는 필드가 해시 테이블의 키로 사용된다. 예시로 'hwibin.success'가 키로 사용되었다고 해보자.

프로브 단계

프로브 단계 동안에는 레코드를 읽기 시작한다. 그리고 각 레코드에서 'velog.success'에 일치하는 레코드를 찾아 결과값을 반환한다.

이를 통해 각 테이블은 한 번씩만 읽게 되어, 중첩해서 2개의 테이블을 읽는 중첩 루프조인보다 보통 성능이 좋다. 사용 가능한 메모리양은 시스템 변수 join_buffer_size에 의해 제어되고, 런타임 시에 조정도 가능하다.

profile
One-step, one-step, steadily growing developer

0개의 댓글