7장에서는 단일 데이터셋에서의 집계 방식만 알아보았다. 하지만 대부분의 경우 다양한 데이터셋을 활용하는 경우가 더 많기에 조인을 활용해 서로 다른 데이터를 조합하여 원하는 형태로 만드는 방법을 알아야 한다. 스파크에서 사용가능한 조인 타입(결과 데이터셋에 어떤 데이터가 존재하는지 결정하는 요소)은 다음과 같다.
- 내부 조인(inner join) : 왼쪽과 오른쪽 데이터셋에 키가 있는 로우를 유지
- 외부 조인(outer join) : 왼쪽이나 오른쪽 데이터셋에 키가 있는 로우를 유지
- 왼쪽 외부 조인(left outer join) : 왼쪽 데이터셋에 키가 있는 로우를 유지
- 오른쪽 외부 조인(right outer join) : 오른쪽 데이터셋에 키가 있는 로우를 유지
- 왼쪽 세미 조인(left semi join) : 왼쪽 데이터셋의 키가 오른쪽 데이터셋에 있는 경우, 키가 일치하는 왼쪽 데이터셋만 유지
- 왼쪽 안티 조인(left anti join) : 왼쪽 데이터셋의 키가 오른쪽 데이터셋에 없는 경우, 키가 일치하는 왼쪽 데이터셋만 유지
- 자연 조인(natural join) : 두 데이터셋에서 종일한 이름을 가진 컬럼을 암시적으로 결합하는 조인을 수행
- 교차 조인(cross join)/카테시안 조인(Cartesian join) : 왼쪽, 오른쪽 모든 로우의 조합으로 결과 생성
조인 사용 시 가장 까다로운 점은 결과 DataFrame에서 중복된 컬럼명을 다루는 경우이다. DataFrame의 각 컬럼은 카탈리스트 애의 고유 ID가 있다. 고유 ID는 카탈리스트 내부에서만 사용할 수 있으며 직접 참조할 수 없기에 중복 컬럼명이 존재하는 경우 특정 컬럼을 참조하기란 매우 어렵다. 이러한 어려움이 야기되는 상황은 두 가지 경우가 있다.
- 조인에 사용할 DataFrame의 특정 키가 동일한 이름을 가지며, 키가 제거되지 않도록 조인 표현식에 명시하는 경우
- 조인 대상이 아닌 두개의 컬럼이 동일한 이름을 가지는 경우
그리고 이러한 어려움을 해결하는 방법에는 3가지 정도가 있다.
- 다른 조인 표현식을 사용 : Boolean 형태의 조인 표현식을 문자열이나 시퀀스 형태로 바꾸면 조인시 중복된 컬럼 중 하나가 자동으로 제거된다.
- 조인 후 컬럼 제거 : 조인 후에 문제되는 컬럼을 제거하는 방법도 있지만, 원본 DataFrame을 참조해야하기에 조인 시 동일한 키 이름을 사용하거나 원본 DataFrame에 동일한 컬럼명이 존재하는 경우에 사용할 수 있다.
- 조인 전 컬럼명 변경 : 조인 전에 중복되는 컬럼명이 없도록 변경하면 문제가 발생하지 않는다.
스파크가 조인을 수행할 때는 두가지 핵심 전략을 이해해야 한다.
- 노드간 네트워크 통신 전략
- 노드별 연산 전략
두가지 전략 중 해당 장에서는 네트워크 통신 전략에 대해 상세히 설명한다. 스파크는 조인 시 전체 노드 간 통신을 유발하는 셔플 조인과 그렇지 않은 브로드캐스트 조인을 활용한다. 몇가지 케이스를 나누어 이해해보자.
큰 테이블끼리 조인이 일어나게 되면 셔플 조인이 발생하는데, 각 테이블이 파티션으로 분리되어 각각의 익스큐터로 분리되어 연산이 수행된다. 연산이 수행되는 과정에 각 노드에 존재하는 키값을 참조해야 하므로 네트워크가 복잡해지고 많은 자원을 필요로 하게 된다.
테이블이 단일 워커 노드 메모리만으로 연산이 가능할 정도로 충분히 작은 경우 연산을 최적화 할 수 있다. 이 경우에는 브로드케스트 조인을 활용하는데, 작은 DataFrame을 전체 노드에 복사하여 처음에만 노드 간의 통신이 발생하도록 하고 이후 연산에는 통신이 일어나지 않아 최적화가 가능하다. 초기 복사하는 과정에서 CPU가 가장 큰 병목구간이 되므로 유의해야 한다.
해당 경우에는 스파크가 조인 방식을 결정하는 것이 가장 바람직하다.