Большие CSV и Parquet: типичные ошибки и решения
Большой файл не обязательно нужно целиком загружать в память. Разбираем, когда читать CSV частями, как обрабатывать Parquet пакетами и почему неверные типы данных или слишком мелкие файлы могут свести выгоду на нет.

Большой CSV может занять в памяти в несколько раз больше места, чем на диске: при чтении парсер создаёт таблицу и отдельные структуры для значений. Parquet экономит место и позволяет читать выбранные столбцы, но вызов, который загружает весь файл, всё равно способен исчерпать RAM. Ниже — практические приёмы для Python 3.11, pandas 2.2 и PyArrow 18.0: как избежать лишней загрузки, ошибок схемы и неудачного разбиения данных.
Сначала выберите способ чтения
Решение зависит не только от формата, но и от операции. Если нужно один раз посчитать сумму в CSV, часто достаточно читать порциями. Если аналитика регулярно обращается к нескольким столбцам большого набора, Parquet с пакетным чтением может быть удобнее. Если же задача требует сортировки всей таблицы или глобального удаления дубликатов, обработка частями потребует отдельной логики: один пакет не видит данные из остальных.
| Подход | Когда подходит | Ограничение |
|---|---|---|
| pandas читает файл целиком | Файл и промежуточные данные уверенно помещаются в память; нужен простой анализ всей таблицы | Фактический расход памяти может существенно превысить размер файла |
| CSV порциями через pandas | Последовательный подсчёт, фильтрация или обработка каждой строки независимо | Глобальные операции требуют дополнительного этапа; типы столбцов нужно задавать явно |
| Parquet пакетами через PyArrow | Нужно читать отдельные столбцы и обрабатывать крупный файл без загрузки целиком | Требуется следить за схемой, размером пакетов и устройством row group |
Термин. Row group — группа строк внутри Parquet-файла, для которой данные каждого столбца хранятся отдельными блоками. Это не то же самое, что пакет строк, который приложение получает за один вызов чтения.
Ошибка 1. Оценивать RAM по размеру CSV
Размер файла на диске не показывает, сколько памяти понадобится pandas. CSV хранит значения как текст; при разборе появляются объекты и внутренние массивы. А если код дополнительно создаёт копию таблицы, например при преобразовании типов или сложной фильтрации, расход растёт ещё сильнее.
Если используете обычный read_csv, заранее ограничьте входные данные столбцами и задайте типы. Если весь набор всё равно не помещается с запасом, читайте его частями. Пример ниже считает сумму числового столбца, не удерживая всю таблицу в памяти. Он рассчитан на CSV с заголовком и числовым столбцом amount.
import pandas as pd
total = 0.0
for chunk in pd.read_csv(
'events.csv',
usecols=['amount'],
dtype={'amount': 'float64'},
chunksize=200_000,
):
total += chunk['amount'].sum()
print(total)
Пакет в 200 тысяч строк — стартовое значение для теста, а не универсальная норма. Уменьшите chunksize, если процесс упирается в память; увеличьте, если память свободна, а накладные расходы на обработку мелких порций заметны. Проверяйте пиковое потребление процесса, а не только размер исходного файла.
Ошибка 2. Надеяться, что pandas сам угадает типы
Автоматическое определение типов удобно для небольших файлов, но в больших данных ошибается на границах и нестандартных значениях. Идентификатор вроде 001234 может потерять ведущие нули, если прочитан как число. Дата в одном фрагменте может выглядеть иначе, чем в другом. А если один пакет содержит только числа, а следующий — пустые строки или служебные значения, обработка может завершиться ошибкой или дать неожиданный тип.
Для важных столбцов задайте тип явно, как в примере выше. Идентификатор, который нельзя складывать или сравнивать как число, обычно нужно читать строкой. Для дат задайте ожидаемый формат на этапе подготовки данных и отдельно решите, что делать с некорректными значениями. Не превращайте ошибку в пропуск молча: сначала посчитайте и изучите такие строки.
Одна из ловушек пакетной обработки — типы могут различаться между порциями. До запуска на полном файле проверьте начало, середину и конец, особенно если данные формируют разные системы. Для воспроизводимой загрузки зафиксируйте схему и проверяйте её при каждом запуске.
Ошибка 3. Читать Parquet целиком, потому что он компактный
Parquet может занимать меньше места и хранить столбцы отдельно, но сам по себе не ограничивает объём чтения в памяти. Вызов pandas.read_parquet возвращает DataFrame: если запросить всю таблицу, приложение всё равно получает весь выбранный набор. Для подсчёта по одному столбцу укажите нужный столбец и читайте файл пакетами через PyArrow.
Пример для Parquet-файла с числовым столбцом amount. Каждый пакет содержит только этот столбец; итоговая сумма накапливается, а весь файл в DataFrame не загружается.
import pyarrow.compute as pc
import pyarrow.parquet as pq
parquet_file = pq.ParquetFile('events.parquet')
total = 0.0
for batch in parquet_file.iter_batches(
batch_size=100_000,
columns=['amount'],
):
total += pc.sum(batch.column(0)).as_py()
print(total)
Если тип столбца целочисленный, результат суммы может быть целым, а не числом с плавающей точкой; здесь переменная принимает оба типа. Для столбца, в котором есть пропуски, заранее проверьте, как они должны влиять на расчёт. Для другой задачи замените сумму на нужную операцию, но убедитесь, что она корректно объединяется по пакетам.
Ошибка 4. Считать пакетную обработку эквивалентом обработки всего набора
Некоторые вычисления легко разбиваются на независимые части: количество строк, сумма, фильтрация по условию. Другие требуют состояния между порциями. Чтобы посчитать среднее, нужно накапливать сумму и количество значений, а не усреднять средние по пакетам, если размеры пакетов отличаются. Чтобы удалить дубликаты во всём файле, недостаточно искать их только внутри каждой порции.
Сортировка всей таблицы и точная медиана тоже не сводятся к независимой обработке порций. Для них нужен алгоритм с дополнительным состоянием, внешняя сортировка или движок, рассчитанный на работу с объёмом больше доступной памяти. Прежде чем писать цикл по пакетам, сформулируйте, какие промежуточные данные нужно сохранить между итерациями и как проверить результат на небольшом полном наборе.
Пакетная загрузка ограничивает память, но не упрощает алгоритм автоматически. Сначала выясните, можно ли корректно объединить результаты отдельных частей.
Ошибка 5. Разбивать Parquet на слишком мелкие файлы
Запись каждого маленького пакета в отдельный Parquet-файл кажется безопасной: данные точно не перезапишутся. Но множество мелких файлов добавляют накладные расходы на открытие, чтение метаданных и поиск нужных данных. При этом слишком крупные блоки могут увеличить задержку чтения и потребление памяти. Универсального размера файла или row group для всех систем нет: он зависит от объёма данных, хранилища, числа читателей и того, какие запросы выполняются.
Если конвертируете CSV в Parquet, заранее определите схему и стратегию разбиения, а не создавайте новый файл на каждый небольшой фрагмент без оценки результата. Прежде чем переносить весь набор, обработайте репрезентативную часть. Сравните объём на диске, время записи, время чтения нужных столбцов и число созданных файлов. Не выбирайте компрессию только по обещанию «меньше»: измерьте, как она влияет на скорость в вашей среде.
Что выбрать и что проверять
- Разовый подсчёт или фильтр по CSV: используйте чтение порциями, явно укажите нужные столбцы и типы. Проверьте результат на небольшом файле, который можно целиком обработать и сравнить.
- Повторные аналитические запросы к одним и тем же данным: рассмотрите Parquet и читайте только нужные столбцы. Перед конвертацией проверьте, что типы и значения не меняются при переходе из CSV.
- Глобальная сортировка, уникальность или точная статистика: не переносите код в цикл по пакетам без изменения алгоритма. Оцените, сколько состояния нужно удерживать, и выберите подход, который это поддерживает.
Типичные сбои проще поймать на тестовом запуске. Проверяйте число прочитанных строк, пропуски, типы столбцов и итоговую сумму или количество. Сверяйте их с независимой проверкой на маленькой выборке. Если значения меняются в середине файла, такая проверка надёжнее, чем тест только на первых строках.
Следующий шаг
Возьмите один реальный файл и измерьте три вещи: пиковую память процесса, время обработки и размер результата. Для CSV сравните чтение целиком с чтением порциями; для Parquet — чтение нужных столбцов пакетами с тем же расчётом. Зафиксируйте размер пакета и схему, при которых результат сходится с контрольным, и только затем запускайте обработку всего набора. Инвалидация и обновление уже записанных Parquet-данных — отдельная задача, здесь речь только о чтении и обработке.
Тест и проверочная: Быстрые ответы с объяснением, почему остальные варианты неверны
Спросить за 10 ₽Источники: pandas: Scaling to large datasets, Apache Arrow: Reading and Writing the Parquet Format
Частые вопросы
Насколько увеличится память при чтении CSV?
Какой размер пакета выбрать для pandas?
Можно ли обрабатывать Parquet через pandas, не загружая весь файл?
Что делать, если код не работает на другой версии pandas или PyArrow?
Почему сумма по пакетам не совпадает с результатом на всей таблице?
Можно ли конвертировать CSV в Parquet, записывая каждый пакет отдельно?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.