Короткий ответ
Единственного правильного решения нет: можно остаться на pandas с чтением по частям (chunking) и оптимизацией типов, перейти на инструменты с ленивым/распределённым выполнением (Dask, Polars, DuckDB, Spark) или агрегировать данные ближе к источнику (SQL на стороне базы/хранилища) — выбор зависит от объёма данных, частоты задачи и имеющейся инфраструктуры.
Как это работает подробнее
chunking в pandas позволяет обрабатывать файл по частям без распределённых вычислений, но усложняет логику, если нужна глобальная операция (сортировка, сложный merge); Dask и Spark распределяют вычисления по многим партициям/узлам, сохраняя API, похожий на pandas, но добавляют накладные расходы на планирование задач; DuckDB и агрегация на стороне SQL-хранилища эффективно считают агрегаты прямо там, где лежат данные, минимизируя объём, который вообще нужно передавать в Python.
Пример кода
import duckdb
result = duckdb.query("""
SELECT category, SUM(amount) AS total
FROM read_csv_auto('big_sales.csv')
GROUP BY category
""").to_df()
print(result)Что использовать на практике
- На практике. если задача — разовая агрегация больших исторических данных, часто эффективнее сначала агрегировать на уровне SQL/хранилища и в pandas забирать уже уменьшенный результат; если нужна сложная построчная логика или множество итераций анализа над одним большим датасетом, оправдан переход на Dask/Polars/Spark с соответствующими трудозатратами на изучение и поддержку.
- Проверка. сравнение времени выполнения и потребления памяти такого SQL-агрегата через DuckDB с эквивалентным построчным чтением и агрегацией в чистом pandas на одном и том же файле наглядно показывает выигрыш от агрегации ближе к данным при больших объёмах.
Подводные камни
- Частые ошибки. сразу переходят на тяжёлую распределённую инфраструктуру (Spark) для задачи, которую можно было решить агрегацией на SQL-уровне или оптимизацией типов в обычном pandas, тратя избыточные ресурсы на поддержку кластера; наоборот, пытаются героически "дотянуть" pandas chunking до объёмов, которые реально требуют распределённой обработки, получая ненадёжный и трудно поддерживаемый код.