행 필터링, 고유값, 샘플링, 합치기, 정렬
Spark: The Definitive Guide (Excerpts, Databricks Preview, 2017) — Chapters 2-6 — Bill Chambers & Matei Zaharia Chapter 5: Filtering Rows, Getting Unique Rows, Random Samples/Splits, Concatenating and Appending Rows, Sorting Rows 절 (PDF pp.75-81)
이 모듈을 다 읽으면
- filter/where의 다중 체이닝이 왜 성능에 불리하지 않은지(파이프라이닝) 설명할 수 있다
- distinct, sample, randomSplit, union의 각 용도를 구분해 설명할 수 있다
- sort/orderBy와 sortWithinPartitions의 차이를 설명할 수 있다
filter와 where는 동일하게 동작하며, 여러 조건을 체이닝해도 Spark가 파이프라이닝으로 한 번에 처리해 성능 손해가 없다. distinct는 중복 제거, sample과 randomSplit은 각각 무작위 표본 추출과 무작위 분할을 담당한다. DataFrame은 불변이라 직접 append할 수 없고 union으로 행을 합치며, sort/orderBy로 정렬하고 sortWithinPartitions으로 전체 셔플 없이 파티션 내부만 정렬할 수 있다.
행 필터링: filter와 where
행을 필터링한다는 것은 참(true) 또는 거짓(false)으로 평가되는 표현식을 만들고, 거짓으로 평가되는 행을 걸러내는 작업이다. filter와 where는 완전히 동일하게 동작하는 메서드이며, DataFrame에서는 받는 인자 타입도 동일하다(다만 Dataset API는 옵션이 조금 다르다).
여러 조건을 하나의 복잡한 표현식에 몰아넣고 싶은 유혹이 들 수 있지만, 꼭 그럴 필요는 없다. AND로 묶이는 여러 필터가 필요하다면 where를 순차적으로 체이닝하기만 하면 된다 - Spark가 모든 필터링 연산을 파이프라이닝(pipelining)해서 한 번에 수행하도록 자동으로 최적화하기 때문에, 체이닝 자체가 성능에 불리하게 작용하지 않는다.
핵심 포인트
- filter와 where는 동일하게 동작하며 인자 타입도 같다(단 Dataset API는 다소 다름)
- 여러 AND 조건은 where를 체이닝해도 Spark가 파이프라이닝으로 한 번에 처리하므로 성능 손해가 없다
고유 행, 샘플링, 랜덤 분할
distinct는 DataFrame에서 중복된 행을 제거해 새 DataFrame을 반환하는 트랜스포메이션이다. 하나의 컬럼 기준으로도, 여러 컬럼 조합 기준으로도 중복 여부를 판단할 수 있다.
sample 메서드는 복원 추출 여부(with replacement), 추출할 비율(fraction), 재현성을 위한 seed를 인자로 받아 DataFrame에서 무작위 표본을 추출한다.
randomSplit은 DataFrame을 무작위로 여러 개의 DataFrame으로 쪼갤 때 쓰는데, 머신러닝에서 학습(train)/검증(validation)/테스트(test) 세트를 나눌 때 자주 활용된다. 각 분할의 비율을 담은 배열과 seed를 인자로 받으며, 만약 비율의 합이 1이 되지 않으면 Spark가 자동으로 정규화해 처리한다.
핵심 포인트
- distinct는 하나 이상의 컬럼 기준으로 중복 행을 제거한 새 DataFrame을 반환한다
- sample은 복원 여부·비율·seed로 무작위 표본을 추출하고, randomSplit은 DataFrame을 비율대로 무작위 분할한다(합이 1이 아니면 자동 정규화됨)
행 합치기(union)와 정렬
DataFrame은 불변(immutable)이므로 이미 존재하는 DataFrame에 행을 직접 append할 수 없다. 대신 원본 DataFrame과 새로 만든 DataFrame을 union해야 하며, union하려는 두 DataFrame은 스키마와 컬럼 개수가 반드시 일치해야 한다 - 그렇지 않으면 union이 실패한다.
정렬에는 sort와 orderBy 두 메서드가 있는데 완전히 동일하게 동작하며, 컬럼 표현식이나 문자열, 여러 컬럼을 인자로 받을 수 있고 기본 정렬 순서는 오름차순이다. 정렬 방향을 명시적으로 지정하고 싶을 때는 asc/desc 함수를 컬럼에 적용한다.
최적화 목적으로, 전체 데이터를 셔플하는 정렬 대신 각 파티션 내부에서만 정렬하고 싶을 때는 sortWithinPartitions을 사용한다.
핵심 포인트
- DataFrame은 불변이라 직접 append할 수 없고, 스키마와 컬럼 수가 같은 두 DataFrame을 union해서 행을 합친다
- sort와 orderBy는 동일하게 동작하며 기본은 오름차순, asc/desc로 컬럼별 방향을 명시할 수 있다
- sortWithinPartitions은 전체 셔플 정렬 없이 파티션 내부만 정렬해 이후 트랜스포메이션 최적화에 활용할 수 있다