Привет, Хабр!
Меня зовут Вадим Москаленко и я разработчик инновационных технологий Страхового Дома ВСК. В этой статье хочу поделится с вами информацией в области хранения данных.
На сегодняшний день существует огромное количество форматов для хранения данных, и, используя библиотеку Pandas при обработке большого объёма данных, возникает вопрос – а какой формат, с которыми Pandas работает «из коробки», даст наибольшую производительность, при дальнейшем использовании, обработанного DataFrame?
Ремарка: поиск информации по этой теме, привёл меня к репозиторию, за авторством Devforfu (ссылка), но так как информация в нём датируется 2019 годом, а за этот период вышло множество обновлений, я решил написать «свежий» бенчмарк, основываясь на принципах автора – ссылка на обновленный бенчмарк. Отмечу, что из-за слишком большой разницы в полученных результатах, я склоняюсь к тому, что мог совершить ошибку, поэтому далее в статье будет указана информация по оригиналу.
В качестве тестируемых форматов использовались следующие варианты: CSV (как самый популярный текстовый формат), Pickle, Feather, Parquet, Msgpack, HDF. Для сравнения будем использовать следующие метрики: размер сериализованного файла, время загрузки DataFrame из файла, время сохранения DataFrame в файл, потребление оперативной памяти при сохранении и загрузке DataFrame.
Тестовые данные – сгенерированный DataFrame с 1 миллионом строк, 15 столбцами цифр и 15 столбцами строковых значений. Генерация численных данных проводилась с помощью numpy. random.normal, в качестве строчных данных использовались UUID. С появлением в Pandas, категориального типа данных (Categorical data), который использует гораздо меньше памяти и более производительней в обработке (обширный материал для другой статьи), интересно также сравнить насколько изменится производительность форматов, поэтому ещё одним этапом сравнения в тестовых данных стал перевод формата «object» к формату «category».
Бенчмарк
Метрики собирались в течении 20 раундов, после чего группировались в результирующий DataFrame по среднему значению. Посмотрим на результаты:
Формат |
RAM, при загрузки файла, Мбайт |
Время загрузки, с |
RAM, при сохранении файла, Мбайт |
Время сохранения, с |
Размер файла, Мбайт |
csv |
385.174219 |
7.179108 |
-0.166406 |
27.588694 |
771.4420 |
feather |
850.572461 |
1.333151 |
635.453125 |
1.966192 |
665.0205 |
hdf |
2602.573047 |
9.296356 |
1337.336523 |
8.668205 |
1644.7400 |
msgpack |
618.167383 |
3.164023 |
1231.050391 |
4.245394 |
637.7340 |
parquet |
883.852148 |
0.634647 |
662.311523 |
2.439488 |
129.1415 |
pickle |
1211.571289 |
2.853154 |
1543.474805 |
5.329675 |
651.4410 |
Результаты:
Лидером по скорости сохранения и загрузки является Parquet, за ним на втором месте Feather, аутсайдером выступил формат CSV.
По росту потребления памяти лидирует текстовый формат CVS, хорошая дельта во время загрузки файла у Msgpack, но высокая при сохранении, поэтому второе место занимает Feather, а на третьем месте Parquet.
По размеру сериализованного файла, с огромным отрывом побеждает Parquet.
Далее, посмотрим на результаты с категориальным типом данных:
Формат |
RAM, при загрузки файла, Мбайт |
Время загрузки, с |
RAM, при сохранении файла, Мбайт |
Время сохранения, с |
Размер файла, Мбайт |
csv |
385.174219 |
7.179108 |
-0.166406 |
27.588694 |
771.4420 |
feather |
10.669531 |
0.044231 |
0.652148 |
0.179261 |
130.5660 |
hdf |
327.377148 |
1.134490 |
8.731445 |
0.909780 |
1269.0565 |
msgpack |
195.321094 |
0.250950 |
175.532813 |
0.332355 |
128.7790 |
parquet |
920.664258 |
0.617414 |
83.697852 |
1.936816 |
128.8640 |
pickle |
135.969922 |
0.118571 |
198.686523 |
0.286379 |
128.7785 |
Так как CSV, на фоне остальных, сильно проигрывает, приведём график без него, для наглядности.
Результаты:
Лидер по скорости изменился и им стал Feather, за ним на втором месте Pickle.
По росту потребления памяти также есть изменения: на первом месте feather, второе делят между собой Pickle/Msgpack и аутсайдером при загрузке файла выступил Parquet.
По размеру сериализованного файла, у Parquet уже нет безоговорочного лидерства.
Файл или База данных?
Получив данные по форматам, стало интересно сравнение производительности с базами данных (далее по тексту – БД). Тут нужно учесть, что основное преимущество хранения в БД — это конкурентный доступ. В случаях, когда он не требуется, хранение данных в файлах обеспечит более прямой и очевидный доступ.
Такое сравнение, с использованием Microsoft SQL Server, привелось в статье – architecture-performance. Краткая выжимка результатов: по скорости чтения БД отстаёт от файлового хранения, а самым быстрым драйвером является Turbodbc.
Итоги
Так как, в одной из первых строк документации Pickle, указано предупреждение о том, что формат небезопасен, можно выделить двух лидеров бенчмарка: Feather и Parquet.
Тип данных |
Object |
Category |
||||
Формат |
feather |
parquet |
% |
feather |
parquet |
% |
Время сохранения, с |
1,97 |
2,44 |
24,07% |
0,18 |
1,94 |
980,44% |
Время загрузки, с |
1,33 |
0,63 |
52,39% |
0,04 |
0,62 |
1295,89% |
Рост потребления памяти при загрузки, Мбайт |
850,57 |
883,85 |
3,91% |
10,67 |
920,66 |
8528,91% |
Рост потребления памяти при сохранении, Мбайт |
635,45 |
662,31 |
4,23% |
0,65 |
83,70 |
12734,18% |
Размер сериализованного файла, Мбайт |
665,02 |
129,14 |
80,58% |
130,57 |
128,86 |
1,30% |
Если в DataFrame не используется категориальный тип данных Pandas, то для долгосрочного хранения больших данных, лучше всего подойдёт формат «Parquet», за счёт минимального размера сериализованного файла. В остальных случаях, формат «Feather» будет самым оптимальным вариантом и позволит с большей скоростью обрабатывать данные, потребляя при этом меньше ресурсов.
Комментарии (13)
lea
16.01.2023 12:37Как интерпретировать отрицательное значение расхода памяти при сохранении в csv?
MentalBlood
16.01.2023 13:02+2Как околонулевой расход памяти при сохранении в csv + погрешность (сборщик мусора сработал, например)
V-Moskalenko Автор
19.01.2023 11:32+1Как верно отметил @MentalBloodтам околонулевой расход текстового формата и погрешность
economist75
16.01.2023 13:54+1Полезно. Из "итогов" как-то легко убрали неплохой вариант, который можно встретить у каждого второго датасайентиста. Pickle (со сжатием) все-таки очень близок к parquet и feather по всем параметрам, и эта троица в целом неплоха и во многом равнозначна.
Единственным заметным минусом pickle назову несовместимость версий для разных сочетаний pandas+python. То есть он плохо пригоден для архивного хранения и редкого обращения. Спустя пару лет старый pkl-файл придется открывать с приключениями.
Минусы есть и у parquet - не на каждую старую ОС или платформу легко его поставить. Но все проблемы имеют решения, в этом экосистема Python сильна, практически нет тропинок, по которым кто-то не прошел (и не оставил след на stackoverflow).
MentalBlood
16.01.2023 14:04+1как-то легко убрали
ACE это не шутки. Впрочем, можно подписывать получаемый файл (но это замедлит загрузку и выгрузку)
CrazyElf
17.01.2023 19:42Я наверное лет 5 назад пробовал разные форматы и остановился тогда на feather в плане скорости записи и чтения. Удивительно, что с тех пор особо ничего не поменялось.
danSamara
19.01.2023 07:19Народ потихоньку переходит на polars. Интересно посмотреть работу с форматами у него.
V-Moskalenko Автор
19.01.2023 11:52Код бенчмарка здесь - ссылка, вы можете попробовать перевести его на Polars, корректировки потребуются в utils.py и main.py. Правда у Polars, не все перечисленные форматы поддерживаются "из коробки".
Беглым запуском (не ручаюсь за точность) у меня получились такие данные, для Parquet и CSV:
7voprosov
Классная статья: минимум воды, понятный вывод
V-Moskalenko Автор
Спасибо, очень приятно, рад что понравилась :)