다양한 데이터소스를 읽고 쓰는 능력과 데이터소스를 커뮤니티에서 자체적으로 만들어내는 능력은 스파크를 가장 강력하게 만들어주는 힘이다!
- 스파크의 핵심 데이터소스
- CSV
- JSON
- 파케이
- ORC
- JDBC/ODBC 연결
- 일반 텍스트 파일
- 커뮤니티에서 만든 데이터소스
- 카산드라
- HBase
- 몽고디비
- AWS Redshift
- XML
📖 데이터소스 API 구조
💫 CSV 파일
- 콤마로 구분된 값
- 스파크는 지연 연산 특성이 있어 데이터 포맷이 스키마와 일치하지 않을 때 DataFrame 정의 시점이 아닌 잡 실행 시점에만 오류가 발생한다.
🍡 JSON 파일
- 스파크에서는 줄로 구분된 JSON을 기본적으로 사용
- 스파크는 JSON 파일을 파싱한 다음에 DataFrame을 생성
- 다른 포맷에 비해 안정적이며, 구조화되어 있고, 최소한의 기본 데이터 타입이 존재한다. 스파크가 적합한 데이터 타입을 추정할 수 있어 원활하게 처리가 가능하다.
- JSON은 객체
🪵 파케이 파일
- 컬럼 기반의 데이터 저장 방식
- 분석 워크로드에 최적화되어 있다.
- 저장소 공간을 절약할 수 있고 전체 파일을 읽는 대신 개별 컬럼을 읽을 수 있으며, 컬럼 기반의 압축 기능을 제공한다.
- 아파치 스파크와 잘 호환되어 스파크의 기본 파일 포맷이다.
- JSON, CSV보다 효율적으로 동작하므로 장기 저장용 데이터는 파케이 포맷으로 저장하는 것이 좋다.
- 복합 데이터 타입을 지원한다. (배열, 맵, 구조체 데이터 타입 등)
- 스파크의 개념에 아주 잘 부합하고 알맞게 정의된 명세를 가지고 있다.
🧙 ORC 파일
- 하둡 워크로드를 위해 설계된 자기 기술적이며 데이터 타입을 인식할 수 있는 컬럼 기반의 파일 포맷
- 대규모 스트리밍 읽기에 최적화되어 있으며, 필요한 로우를 신속하게 찾아낼 수 있는 기능이 통합되어 있다.
- 파케이는 스파크에 최적화된 반면, ORC는 하이브에 최적화되어 있다.
🦑 SQL 데이터베이스
- SQL 데이터소스는 매우 강력한 커넥터 중 하나
- SQL을 지원하는 다양한 시스템에 SQL 데이터소스를 연결할 수 있다.
- 데이터베이스는 원시 파일 형태가 아니므로 인증 정보, 접속 관련 옵션 등 고려해야 할 옵션이 더 많다.
- 스파크 클러스터에서 데이터베이스 시스템이 접속 가능한지 네트워크 상태를 확인해야 한다.
⬇️ 쿼리 푸시다운
스파크는 코든 스파크 함수를 사용하는 SQL 데이터베이스에 맞게 변환하지는 못한다. 따라서 전체 쿼리를 데이터베이스에 전달해 결과를 DataFrame으로 받아야 하는 경우가 있다.
→ 테이블명 대신 SQL 쿼리를 명시하고, 테이블에 쿼리할 때 명시한 쿼리를 사용해 수행한다.
🍫 데이터베이스 병렬로 읽기
스파크는 파일 크기, 파일 유형, 그리고 압축 방식에 따른 '분할 가능성'에 따라 여러 파일을 읽어 하나의 파티션으로 만들거나 여러 파티션을 하나의 파일로 만드는 기본 알고리즘을 가지고 있다.
numPartitions 옵션을 사용해 읽기 및 쓰기용 동시 작업 수를 제한할 수 있는 최대 파티션 수를 설정할 수 있다.
데이터베이스 연결을 통해 명시적으로 조건절을 SQL 데이터베이스에 위임할 수 있다. 조건절을 명시함으로써 특정 파티션에 특정 데이터의 물리적 위치를 제어할 수 있다.
🎢 슬라이딩 윈도우 기반의 파티셔닝
조건절을 기반으로 분할할 수 있는 방법.
🗒️ 텍스트 파일
- 일반 텍스트 파일
- 파일의 각 줄이 DataFrame의 레코드가 된다.
- 아파치 로그 파일을 구조화된 포맷으로 파싱하거나, 자연어 처리를 위해 일반 텍스트를 파싱하는 경우를 예로 들 수 있다.
- 기본 데이터 타입의 유연성을 활용할 수 있으므로 Dataset API에서 사용하기 좋은 포맷이다.
🌬️ 고급 I/O 개념
- 분할 가능한 파일 타입과 압축 방식
- 분할이 가능한 경우 전체 파일이 아닌 쿼리에 필요한 부분만 읽을 수 있으므로 성능 향상에 도움이 된다.
- HDFS와 같은 시스템을 사용한다면 분할된 파일이 여러 블록으로 나누어 분산 저장하기 때문에 더 최적화할 수 있다.
- 압축 방식도 함께 관리해야 한다. (파케이 파일 포맷, GZIP 압축 방식)
- 병렬로 데이터 읽기
- 다수의 파일이 존재하는 폴더를 읽을 때 폴더의 개별 파일은 DataFrame의 파티션이 된다. 따라서 사용 가능한 익스큐터를 이용해 병렬로 파일을 읽는다.
- 병렬로 데이터 쓰기
- 기본적으로 데이터 파티션 당 하나의 파일이 작성된다.
- 옵션에 지정된 파일명은 실제로는 다수의 파일을 가진 디렉터리, 디렉터리 안에 파티션 당 하나의 파일로 데이터를 저장한다.
- 파티셔닝
- 어떤 데이터를 어디에 저장할 것인지 제어할 수 있는 기능
- 파티션된 디렉터리 또는 테이블에 파일을 쓸 때 디렉터리 별로 컬럼 데이터를 인코딩해 저장한다.
- 따라서 데이터를 읽을 때 필요한 컬럼의 데이터만 읽을 수 있다.
- 필터링을 자주 사용하는 테이블을 가진 경우 사용할 수 있는 가장 손쉬운 최적화 방식
- 버케팅
- 각 파일에 저장된 데이터를 제어할 수 있는 파일 조직화 기법
- 동일한 버킷 ID를 가진 데이터가 하나의 물리적 파티션에 모두 모여 있기 때문에 데이터를 읽을 때 셔플을 피할 수 있다.
- 데이터가 이후의 사용 방식에 맞춰 사전에 파티셔닝되므로 조인이나 집계시 발생하는 고비용의 셔플을 피할 수 있다.
- 파일 크기 관리
- 작은 크기의 파일 여러 개 / 너무 큰 파일 하나 → 문제가 될 수 있음
- 결과 파일을 최적의 크기로 제한할 수 있는 기능 존재
- 각 파일에 기록될 레코드 수 조절
[출처] 스파크 완벽 가이드 (빌 체임버스, 마테이 자하리아 지음)