Конвертировать датасет из JSONL в Parquet
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Конвертировать датасет из JSONL в Parquet
1. Цель задачи
Научиться эффективно конвертировать большие датасеты из формата JSONL (JSON Lines) в колоночный формат Parquet с использованием библиотек Pandas и Dask. Сравнить размер файлов на диске и скорость чтения данных из каждого формата, чтобы убедиться в преимуществах Parquet для аналитических нагрузок.
Ключевой результат Получить Parquet-файл, который в 5–10 раз меньше исходного JSONL и читается в 3 и более раз быстрее при выполнении типовых операций (фильтрация, агрегация).
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Датасет в формате JSONL (минимум 500 000 строк, 10–20 колонок разных типов) | Сгенерировать синтетически (см. ниже) или скачать публичный (например, amazon_reviews, wikipedia в JSONL) |
| Python 3.10+ | Установить из официального дистрибутива |
| Библиотеки: pandas, dask, pyarrow, fastparquet, numpy, psutil | pip install pandas dask[complete] pyarrow fastparquet numpy psutil |
| Скрипты для бенчмаркинга | Написать самостоятельно в рамках задачи |
Если нет реального инструмента — симулируем:
- Сгенерировать dataset|синтетический датасет с помощью Python:
- Убедиться, что размер файла не менее 200 МБ (при необходимости увеличить количество строк или длину строковых полей).
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Язык программирования | Python 3.10+ | Основной язык для скриптов |
| Обработка данных (однопоточная) | Pandas 2.x | Загрузка JSONL, конвертация в Parquet, чтение |
| Обработка данных (распределённая) | Dask 2024.x | Потоковая/чанковая конвертация для больших данных |
| Формат Parquet | PyArrow / fastparquet | Запись и чтение Parquet-файлов |
| Генерация данных | NumPy, random, json | Создание синтетического датасета |
| Измерение времени и памяти | timeit, psutil, os.path.getsize | Бенчмаркинг |
4. Этапы выполнения
Этап 1: Подготовка данных и окружения (30 минут)
Действия
- Установить все необходимые библиотеки (см. раздел 2).
- Создать скрипт
generate_dataset.pyдля генерации синтетического датасета: - Убедиться, что файл создан и доступен для чтения.
Пример кода генерации (фрагмент):
import json
import numpy as np
from datetime import datetime, timedelta
N = 1_000_000
categories = ['A', 'B', 'C', 'D'] * 5
start_date = datetime(2020, 1, 1)
with open('dataset.jsonl', 'w') as f:
for i in range(N):
row = {
'id': i,
'timestamp': (start_date + timedelta(seconds=i)).isoformat(),
'category': np.random.choice(categories),
'value': round(np.random.uniform(0, 1000), 2),
'description': ' '.join(np.random.choice(['word']*10, size=20)),
'flag': bool(np.random.randint(0, 2)),
'nested': {'a': i % 10, 'b': np.random.rand(), 'c': 'x' * 5}
}
f.write(json.dumps(row) + '\n')
Ожидаемый результат этапа Файл dataset.jsonl размером >200 МБ, готовый к конвертации.
Этап 2: Конвертация с помощью Pandas (1 час)
Действия
- Написать скрипт
convert_pandas.py:- Загрузить JSONL в DataFrame с помощью pd.read_json('dataset.jsonl', lines=True).
- Замерить время загрузки и объём памяти (через psutil).
- Сохранить DataFrame в Parquet: df.to_parquet('dataset_pandas.parquet', index=False, engine='pyarrow').
- Замерить время записи.
- Вывести размеры исходного и результирующего файлов.
- Прочитать Parquet обратно: pd.read_parquet('dataset_pandas.parquet') — замерить время.
- Выполнить простую агрегацию (например, среднее value по
category) на JSONL (через загрузку) и на Parquet — сравнить время выполнения.
Ожидаемый результат этапа Parquet-файл создан, получены первые метрики размера и скорости.
Этап 3: Конвертация с помощью Dask (1 час)
Действия
- Написать скрипт
convert_dask.py: - Прочитать Parquet через Dask и выполнить ту же агрегацию, что и в этапе 2.
- Сравнить время выполнения с Pandas-версией.
Ожидаемый результат этапа Второй Parquet-файл (или единый, если Dask слил в один), метрики для Dask.
Этап 4: Бенчмаркинг и сравнение (1 час)
Действия
- Написать скрипт benchmark.py, который выполняет следующие замеры для каждого формата (JSONL, Pandas-Parquet, Dask-Parquet):
- Повторить каждый замер 3 раза, взять среднее.
- Вывести таблицу сравнения:
| Формат | Размер (МБ) | Время чтения (с) | Время агрегации (с) | Память (МБ) |
|---|---|---|---|---|
| JSONL | ... | ... | ... | ... |
| Pandas Parquet | ... | ... | ... | ... |
| Dask Parquet | ... | ... | ... | ... |
- Рассчитать коэффициенты: сжатие (размер JSONL / размер Parquet) и ускорение (время JSONL / время Parquet).
Ожидаемый результат этапа Численные метрики, подтверждающие или опровергающие целевые показатели (5–10x сжатие, 3x+ ускорение).
Этап 5: Анализ и документирование (30 минут)
Действия
- Написать краткий отчёт
report.md, включающий:- Описание датасета и окружения.
- Таблицу с результатами бенчмарка.
- Выводы: достигнуты ли целевые показатели, какой подход (Pandas vs Dask) оказался эффективнее для данного объёма данных.
- Рекомендации по выбору формата для production-сценариев.
- Зафиксировать все скрипты и файлы в репозитории (опционально).
Ожидаемый результат этапа Файл report.md с анализом, готовый к ревью.
5. Критерии приемки (Definition of Done)
- Сгенерирован датасет в JSONL размером не менее 200 МБ.
- Parquet-файл создан с помощью Pandas и Dask (два отдельных файла или один, если Dask слил).
- Размер Parquet-файла меньше размера JSONL минимум в 5 раз.
- Время чтения Parquet (любым способом) меньше времени чтения JSONL минимум в 3 раза.
- Время агрегации на Parquet меньше времени агрегации на JSONL минимум в 3 раза.
- Все замеры выполнены не менее 3 раз, результаты усреднены.
- Написан отчёт
report.mdс таблицей и выводами. - Код скриптов воспроизводим (зафиксированы версии библиотек в requirements.txt).
6. Ожидаемый результат
Основной артефакт Репозиторий (или папка) со следующими файлами:
- dataset.jsonl — исходный датасет.
- dataset_pandas.parquet — результат конвертации через Pandas.
- dataset_dask.parquet — результат конвертации через Dask (может быть директорией с партициями).
generate_dataset.py— скрипт генерации.convert_pandas.py— скрипт конвертации Pandas.convert_dask.py— скрипт конвертации Dask.- benchmark.py — скрипт бенчмаркинга.
report.md— отчёт с результатами.- requirements.txt — список зависимостей.
Дополнительно (опционально): Графики зависимости времени чтения от размера данных (если сделать несколько датасетов разного объёма).
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Нехватка оперативной памяти при загрузке большого JSONL в Pandas | Использовать Dask с чанками или читать JSONL построчно через json.loads и накапливать в список с последующим pd.DataFrame (но это медленно). Либо уменьшить размер датасета до 500k строк. |
| Разные версии Parquet (pyarrow vs fastparquet) дают разный размер | Использовать один движок (pyarrow) для всех экспериментов. |
| Dask создаёт несколько файлов-партиций | Замерить суммарный размер всех партиций. Для чтения использовать dask.dataframe.read_parquet — он автоматически объединит. |
| Время записи Parquet может быть больше, чем время записи JSONL | Это ожидаемо, цель — ускорение чтения, а не записи. Замерить отдельно. |
| Шум в замерах из-за фоновых процессов | Выполнять замеры на «холодную» (сбросить кэш ОС) или повторять 3+ раз и брать медиану. |
8. Бюджет времени (оценка)
| Этап | Время |
|---|---|
| Этап 1: Подготовка данных и окружения | 30 мин |
| Этап 2: Конвертация с Pandas | 1 ч |
| Этап 3: Конвертация с Dask | 1 ч |
| Этап 4: Бенчмаркинг и сравнение | 1 ч |
| Этап 5: Анализ и документирование | 30 мин |
| Итого | 4 ч |
Примечание Для первого выполнения задачи рекомендуется заложить до 6 часов с учётом отладки и изучения документации.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 42 | Форматы хранения данных: JSON vs Parquet vs Avro |
| 87 | Оптимизация чтения больших файлов в Pandas |
| 134 | Dask: отложенные вычисления и чанкование |
| 211 | Сжатие в Parquet: Snappy, Gzip, Zstd |
| 298 | Бенчмаркинг производительности I/O в Python |
| 356 | Работа с JSONL: потоковая загрузка |
| 412 | Колоночные форматы vs строчные: когда что использовать |
| 489 | Управление памятью при обработке больших датасетов |
| 567 | PyArrow vs fastparquet: сравнение движков |
| 634 | Практика: конвертация логов из JSON в Parquet |
10. Чек-лист самопроверки
- Я сгенерировал датасет и убедился, что он корректен (валидный JSON, нужное количество строк).
- Я выполнил конвертацию через Pandas и Dask, получив Parquet-файлы.
- Я написал скрипт бенчмарка, который измеряет размер, время чтения и агрегации, и память.
- Я проверил, что Parquet действительно меньше JSONL в 5+ раз и читается быстрее в 3+ раза.
- Я задокументировал все шаги и результаты в
report.md, включая таблицу и выводы.