[Python] 파케이(Parquet)
파케이(Parquet)
Pandas나 PySpark등을 사용하다보면 *.csv 포맷으로는 만족하지 못하는 경우가 많다.
예를 들어
- Data Type이 저장되지 않는다.
- 너무 많은 데이터는 저장해도 CSV의 이점(엑셀로 열어볼 수 있다)을 살리지 못한다.
- 특정 Column만 선택하는 것이 불가능하다. (= 전체 파일을 항상 모두 열어야 한다)
- 용량이 상대적으로 작지만 크다 (압축을 하지 않은 경우)
- (종종) Escaping이 잘 되지 않은 경우에는 파일 Parsing이 깨진다.
- 한글이 들어간 csv의 경우 “MS Excel”에서는 BOM이 없으면 UTF-8을 제대로 인식하지 못한다. (한편, EUC-KR 인코딩은 잘 읽는다.)
등등 여러가지 이슈가 있다. 그렇다면 어떤 형식을 써야할까?
CSV vs. JSON vs. Parquet
원본 데이터를 곧바로 가져다 사용하는 경우(=Athena, RedShift, BigQuery, DB 등이 데이터소스가 아닌 경우)에는 보통 csv, json, parquet 이 세가지 형식이 가장 범용적이다.
그 중에서도 특히 csv와 json을 자주 사용한다.
작은 데이터의 경우 csv를, API에서는 json을 제공하는 경우가 많다.
그림에서 볼 수 있듯 파일 형식에 따라 표현할 수 있는 방식이 다르다.
하지만 결론은 대부분 “Parquet 파일을 써라!” 인 경우가 많다.
컬럼기반 저장 포맷
컬럼기반(열 지향) 데이터베이스는 컬럼단위로 데이터가 저장이 된다. 그래서 데이터를 미리 컬럼단위로 압축시키고, 필요한 컬럼만 빠르게 읽고, 집계하는데 있어서 빠르다.
- 일반적인 데이터구조
사람들이 생각하는 데이터 구조
- 행 기반 저장 방식
실제 데이터 저장 방식
- 컬럼 기반의 저장 방식
Parquet 형식의 데이터 저장 방식
마찬가지로 컬럼기반 저장포맷인 파케이의 목적도 필요한 데이터만 디스크로부터 읽어 I/O를 최소화하고, 데이터 크기를 줄이는 것이다.
Parquet의 장점
컬럼 기반의 저장 방식이 주는 이점 세가지를 들 수 있습니다.
- 압축률이 더 좋다. 유사한 데이터들이 모여있기 때문에 데이터들이 많이 모이면 압축하기가 좋습니다. 이는 압축 방식에 대한 이해가 필요합니다.
- I/O 사용률이 줄어든다. 데이터를 읽어 들일 때 일부 컬럼만을 스캔하기 때문입니다.
- 컬럼별로 적합한 인코딩을 사용할 수 있다. 각 컬럼의 데이터들은 동일한 유형의 데이터를 저장하기 때문입니다. 따라서 컬럼마다 서로 다른 (데이터형에 유리한) 인코딩을 사용할 수 있습니다.
Apache Parquet는 레코드 조각내기 및 조립 알고리즘을 사용하여 구현합니다. 여기에는 데이터 저장에 사용할 수 있는 복잡한 데이터 구조가 포함됩니다. Parquet는 복잡한 데이터를 대량으로 다루는 데 최적화되어 있으며 다양한 방식을 동원해 효율적인 데이터 압축과 인코딩 유형을 제공합니다. 이 방식은 특히 대규모 테이블에서 특정 컬럼을 읽어야 하는 쿼리에 가장 좋습니다. Parquet는 필요한 컬럼만 읽으므로 IO가 대폭 최소화되기 때문입니다.
파일 타입별 벤치마크
파일 형식에 따른 데이터 저장, 로드 시간 비교
- csv는 로드/저장시 high comp low io로 처리할 수 있다. 호환성이 뛰어나고 변환 가능한 포맷에서는 위력을 발휘할 수 있다. 하지만 특정 데이터를 다룬다면 다른 포맷을 꼭 확인해 봐야한다.
파일 형식에 따른 I/O시의 메모리 사용량
- 메모리 관련하여 hdf은 좋지 않은 성능을 보여준다. csv는 저장 /로드 일반 텍스트 문자열 동안 추가 메모리를 필요하지 않는다.(바로 저장한다) feather와 parquet 매우 좋은 성능을 나타낸다.
파일 형식에 따른 저장되는 파일의 크기
- 파일 크기. parquet 형식은 대량의 데이터를 효율적으로 저장하기 위해 개발되었다.
파이썬으로 parquet 사용하기 예제
pandas에서의 간단한 parquet 사용하기(읽기/쓰기)
# !pip install fastparquet
# save
import pandas as pd
df = pd.DataFrame()
df.to_parquet('sample.parquet', compression='gzip')
# read
df = pd.read_parquet('sample.parquet')
print(df)
Snappy
Parquet형식은 Pandas에서 기본 옵션으로 Snappy 압축을 사용한다.
Snappy 압축은 구글에서 자체 개발한 압축 라이브러리이며, 최고의 압축률 보다는 적정 수준의 압축률을 제공하면서 빠르게 압축하고 해제하는 것을 목표로 한다.
Gzip
Snappy 압축이 좋기는 하지만 위와 같이 빌드 관련한 의존 패키지도 설치해야하고(꽤 무겁다), 때로는 의존성 라이브러리도 이슈가 종종 있어 사용하기 까다로운 측면이 있다.
따라서 시스템에서 보통 기본적으로 잘 지원하는 gzip 형식을 이용하기도 한다.
압축률은 gzip > snappy이며, 압축 속도는 gzip < snappy로 약간의 차이는 있다.
df = pd.DataFrame()
df.to_parquet('sample.parquet', compression='gzip')
한편, 어떤 압축 방식(Gzip/Snappy/Uncompressed)을 사용하든 파일을 읽는 방식은 동일하다.
이때는 압축 방식을 알아서 유추해서 풀기 때문에 별도의 옵션을 주지 않아도 된다.
df = pd.read_parquet('sample.parquet')
또한 특정 컬럼만 읽으려고 한다면 아래와 같이 columns 인자를 전달하면 파일 전체 대신 해당 컬럼만 읽어서 DataFrame을 생성한다.
df = pd.read_parquet('sample.parquet', columns=['a', 'b'])
실제 사용 사례
Airbnb
- Airbnb는 마켓플레이스의 데이터를 저장하고 분석하기 위해 Parquet를를 사용합니다.
- Airbnb는 Parquet를 활용해 저장 비용을 줄이고 쿼리 성능을 향상시켜 매일 수십억 줄의 데이터를 처리할 수 있게 했습니다.
- Twitter는 Parquet를 사용하여 트윗, 사용자 상호 작용 및 광고 노출을 비롯한 방대한 데이터 세트를 저장하고 분석합니다.
- Parquet를 사용하여 Twitter는 쿼리 성능을 개선하고 저장 비용을 줄이는 동시에 JSON과 같은 복잡한 데이터 구조도 지원합니다.
Uber
Uber는 Parquet를 사용하여 초당 수백만 건의 이벤트가 포함된 승차 및 운전자 데이터를 저장하고 분석합니다. Uber는 Parquet를 활용해 쿼리 성능을 개선하고 저장 비용을 줄여 방대한 양의 데이터를 실시간으로 처리할 수 있게 했습니다.
댓글남기기