Лучший формат данных, для хранения pandas.DataFrame

91a1ca68cd571f50a435bd7dba1b301c.jpg

Привет, Хабр!

Меня зовут Вадим Москаленко и я разработчик инновационных технологий Страхового Дома ВСК. В этой статье, хочу поделится с вами, информацией в области хранения данных.

На сегодняшний день существует огромное количество форматов для хранения данных, и, используя библиотеку 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

d87a003e79e1b9b43913be722bf9bd39.pngf40254221f6c9062b4ecbe43a8c1cdcd.png0aed059d4027d9cee424b2caba1f02a1.png

Результаты:

  • Лидером по скорости сохранения и загрузки является 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

59f8d2c3cd359c62e80d9dd4506bfe05.png

Так как CSV, на фоне остальных, сильно проигрывает, приведём график без него, для наглядности.

183a5ee07949511e2ba20b0b9ce7bb09.png3c2077294fd37e74e8d75b281ce1bc9b.png4f8125c5a4532327bb2f36417cbe5e2c.png

Результаты:

  • Лидер по скорости изменился и им стал Feather, за ним на втором месте Pickle.

  • По росту потребления памяти также есть изменения: на первом месте feather, второе делят между собой Pickle/Msgpack и аутсайдером при загрузке файла выступил Parquet.

  • По размеру сериализованного файла, у Parquet уже нет безоговорочного лидерства.

Файл или База данных?

Получив данные по форматам, стало интересно сравнение производительности с базами данных (далее по тексту — БД). Тут нужно учесть, что основное преимущество хранения в БД — это конкурентный доступ. В случаях, когда он не требуется, хранение данных в файлах обеспечит более прямой и очевидный доступ.

Такое сравнение, с использованием Microsoft SQL Server, привелось в статье — architecture-performance. Краткая выжимка результатов: по скорости чтения БД отстаёт от файлового хранения, а самым быстрым драйвером является Turbodbc.

0dda0e8e32e453255f7f5d785733cacb.png

Итоги

Так как, в одной из первых строк документации 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» будет самым оптимальным вариантом и позволит с большей скоростью обрабатывать данные, потребляя при этом меньше ресурсов.

© Habrahabr.ru