최근에 mySQL을 다시 공부하면서 대용량 데이터를 DB에 적재하고, 조회하는 시간을 줄이는 방법에 대해서 고민했습니다. 평소 데이터를 읽을 때 pandas를 애용하고, 파일 형식을 csv나 json으로 맞춰서 데이터를 처리하는 것을 선호했습니다.
이번 포스팅은 대용량 데이터를 pandas로 읽는데 시간이 얼마나 걸리고, 이것을 개선할 pyarrow를 사용해보고 비교해보겠습니다. 그리고 parquet 파일 형식으로 파일 용량을 줄여서 저장해보겠습니다.
데이터 : ecommerce 웹 로그 데이터이며 천만 개의 row와 2G 데이터입니다.
Parquet
파케이(parquet)는 하둡에서 칼럼 방식으로 저장하는 저장 포맷입니다. 전통적인 방식인 행 기반 압축 대신 열 기반 압축을 사용하여 같은 칼럼의 데이터가 연속된 구조로 저장됩니다.
행 기반 압축에 비해 데이터의 압축률이 더 높고, 필요한 열의 데이터만 읽어서 처리하는 것이 가능하기 때문에 데이터 처리에 들어가는 자원을 절약할 수 있습니다.
Pandas
pandas의 read_csv를 사용하여 읽고 데이터 프레임 형식으로 저장
읽는 데는 약 13초 걸리지만 저장하는데 4배의 시간이 걸립니다.
def read_pandas():
start = time.time()
ecommerce = pd.read_csv(ORIGIN_FILE_PATH, index_col = 0)
print("데이터 shape :", ecommerce.shape)
ecommerce.to_csv("ecommerce_test.csv")
end = time.time()
sec = (end - start)
print("걸린 시간 : ", datetime.timedelta(seconds=sec))
pandas의 read_csv를 사용하여 읽고 parquet 형식으로 저장
읽는 데는 약 13초 걸리지만 저장하는데 3배의 시간이 걸립니다.
def read_pandas():
start = time.time()
ecommerce = pd.read_csv(ORIGIN_FILE_PATH, index_col = 0)
print("데이터 shape :", ecommerce.shape)
ecommerce.to_parquet(PARQUET_FILE_PATH, compression="gzip")
end = time.time()
sec = (end - start)
print("걸린 시간 : ", datetime.timedelta(seconds=sec))
parquet 형식으로 저장하니깐 용량도 기존 csv 파일보다 7배나 줄일 수 있었습니다.
Pyarrow
pyarrow는 python에서 제공해주는 Apache Arrow입니다.
Apache Arrow는 Columnar In-Memory 포맷으로 parquet 파일을 읽고 변환하는데 효과적입니다. (pyarrow, parquet 깐부)
pyarrow를 사용할 경우 기본적으로 table이라는 데이터 타입을 생성하는데 그것을 pandas로 바꾸면 dataframe으로 저장할 수 있습니다.
pyarrow를 사용하여 읽고 데이터 프레임 형식으로 저장
확실히 읽는 시간이 pandas보다 3배나 빠른 것을 보여줍니다. 하지만, 읽는 시간에 비해 저장 시간이 오래 걸리는 것을 확인할 수 있습니다.
import time
import pandas as pd
import datetime
import pyarrow.csv as pc
def read_pyarrow():
start = time.time()
ecommerce = pc.read_csv(ORIGIN_FILE_PATH, parse_options=pc.ParseOptions(delimiter="\t"))
ecommerce = ecommerce.to_pandas()
print("데이터 shape :", ecommerce.shape)
ecommerce.to_csv("C:/Users/com/Downloads/2019-Nov/saved_2019_Nov.csv")
end = time.time()
sec = (end - start)
print("걸린 시간 : ", datetime.timedelta(seconds=sec))
pyarrow를 사용하여 읽고 parquet 형식으로 저장
와우 확실히 pyarrow가 parquet 형식 전용이다 보니깐 pandas와 차원이 다른 속도를 보여줍니다. (정말 애용해야겠습니다)
import time
import pandas as pd
import datetime
import pyarrow as pa
import pyarrow.parquet as pq
import pyarrow.csv as pc
def read_pyarrow():
start = time.time()
ecommerce = pc.read_csv(ORIGIN_FILE_PATH, parse_options=pc.ParseOptions(delimiter="\t"))
ecommerce = ecommerce.to_pandas()
print("데이터 shape :", ecommerce.shape)
# ecommerce.to_csv("C:/Users/com/Downloads/2019-Nov/saved_2019_Nov.csv")
table = pa.Table.from_pandas(ecommerce)
pq.write_table(table, PARQUET_FILE_PATH)
end = time.time()
sec = (end - start)
print("걸린 시간 : ", datetime.timedelta(seconds=sec))
신기하게도 pandas를 parquet 파일로 저장한 것보다는 크기 압축이 되진 않았습니다. 그래도 기존 파일보다 2배 정도 압축이 되었습니다.
panquet 파일을 pandas df으로 읽는 방법은 pq(위에서 선언).read_table({파일 위치}).to_pandas() 를 사용하시면 됩니다.
df = pq.read_table({file_path}).to_pandas()
정리
(열 인덱스) 읽기 방식 (행 인덱스) 저장 방식 |
pandas | pyarrow |
dataframe | 읽기 : 12초 읽고 저장 : 1분 3초 |
읽기 : 4초 읽고 저장 : 43초 |
panquet | 읽기 : 12초 읽고 저장 : 48초 |
읽기 : 4초 읽고 저장 : 10초 |
"대용량 데이터는 pyarrow로 읽고 panquet 방식으로 저장하면 시간 효율성이 가장 좋다"
'python' 카테고리의 다른 글
[python] lambda/map/filter (0) | 2022.04.03 |
---|---|
[python] csv (0) | 2022.04.03 |
[python] operator.itemgetter (2) | 2022.04.01 |
[python] string.punctuation (2) | 2022.03.30 |
[python] 딕셔너리/JSON/집합 (0) | 2022.01.29 |
댓글