책 '면접을 위한 CS 전공지식 노트'를 읽고 정리한 내용입니다.
조인(Join)
- 조인이란 하나의 테이블이 아닌 두 개 이상의 테이블을 묶어서 하나의 결과물을 만드는 것을 말한다.
- MySQL에서는 JOIN, MongoDB에서는 lookup이라는 쿼리로 처리할 수 있다.
- MongoDB에서는 lookup은 되도록 사용하지 말아야 한다. NoSQL은 RDBMS보다 JOIN 연산의 성능이 떨어진다고 알려져 있다.
- 여러 테이블을 조인하는 작업이 많을 경우 MongoDB보다는 RDBMS를 사용해야 한다.
조인의 종류
내부 조인(inner join)
왼쪽 테이블과 오른쪽 테이블의 두 행이 모두 일치하는 행이 있는 부분만 표기한다.
select *
from tableA A
inner join tableB B
on A.key = B.key
왼쪽 조인(left outer join)
left join은 테이블 B의 일치하는 부분의 레코드와 함께 테이블 A를 기준으로 완전한 레코드 집합을 생성한다. 만약 테이블 B에 일치하는 항목이 없으면 해당 값은 Null 값이 된다.
select *
from tableA A
left join tableB B
on A.key = B.key
오른쪽 조인(right outer join)
right join은 테이블 A에서 일치하는 부분의 레코드와 함께 테이블 B를 기준으로 완전한 레코드 집합을 생성한다. 만약 테이블 A에 일치하는 항목이 없으면 해당 값은 Null 값이 된다.
select *
from tableA A
right join tableB B
on A.key = B.key
합집합 조인(full outer join)
합집합 조인은 양쪽 테이블에서 일치하는 레코드와 함께 테이블 A와 테이블 B의 모든 레코드 집합을 생성한다. 이 때 일치하는 항목이 없으면 누락된 쪽에 Null 값이 포함되어 출력한다.
select *
from tableA A
full outer join tableB B
on A.key = B.key
SQL의 JOIN을 시각화해서 볼 수 있는 사이트(https://sql-joins.leopard.in.ua/)
조인의 원리
중첩 루프 조인
중첩 루프 조인(NLJ, Nested Loop Join)은 중첩 for문과 같은 원리로 조건에 맞는 조인을 하는 방법이다. 랜덤 접근에 대한 비용이 많이 증가하므로 대용량의 테이블에서는 사용하지 않는다.
“t1, t2 테이블을 조인한다”라고 했을 때 첫 번째 테이블에서 행을 한 번에 하나씩 읽고 그 다음 테이블에서도 행을 하나씩 읽어 조건에 맞는 레코드를 찾아 결괏값을 반환한다.
for each row in t1 matching reference key {
for each row in t2 matching reference key {
if row satisfies join conditions, send to client
}
}
정렬 병합 조인
정렬 병합 조인이란 각각의 테이블을 조인할 필드 기준으로 정렬하고 정렬이 끝난 이후에 조인 작업을 수행하는 조인이다.
조인할 때 사용할 적절한 인덱스가 없고 대용량의 테이블들을 조인하고 지인 조건으로 <. > 등 범위 비교 연산자가 있을 때 사용한다.
해시 조인
해시 조인은 해시 테이블을 기반으로 조인하는 방법이다. 두 개의 테이블을 조인한다고 했을 때 하나의 테이블이 메모리에 온전히 들어간다면 보통 중첩 루프 조인보다 효율적이다.(메모리에 올릴 수 없을 정도로 크다면 디스크를 사용하는 비용이 발생된다.) 또한, 동등(=) 조인에서만 사용할 수 있다.
MySQL의 경우 MySQL8.0.18 릴리스와 함께 이 기능을 사용할 수 있다. MySQL의 해시 조인 단계는 빌드 단계, 프로브 단계로 나뉜다.
빌드 단계
입력 테이블 중 하나를 기반으로 메모리 내 해시 테이블을 빌드하는 단계
예를 들어 persons와 countries라는 테이블을 조인한다고 했을 때 둘 중에 바이트가 더 작은 테이블을 기반으로 해시 테이블을 빌드한다.
또한, 조인에 사용되는 필드가 해시 테이블의 키로 사용된다. ‘countires.country_id’가 키로 사용된느 것을 볼 수 있다.
프로브 단계
프로브 단계 동안 레코드 읽기를 시작하며, 각 레코드에서 ‘persons.country_id’에 일치하는 레코드를 찾아서 결괏값으로 반환한다.
이를 통해 각 테이블은 한 번씩만 읽게 되어 중첩해서 두 개의 테이블을 읽는 중첩 루프 조인보다 보통은 성능이 더 좋다.
참고로 사용 가능한 메모리양은 시스템 변수 join_buffer_size에 의해 제어되며, 런타임 시에 조정할 수 있다.
'책' 카테고리의 다른 글
면접을 위한 CS 전공지식 노트 - 시간 복잡도 (0) | 2023.04.18 |
---|---|
Clean Code - 의미있는 이름 (0) | 2023.04.17 |
Clean Code - 객체와 자료구조 (1) | 2023.04.12 |
Clean Code - 단위 테스트(FIRST) (0) | 2023.04.11 |
Clean Code - 클래스 (0) | 2023.04.06 |