Функция write_dataset() создает тысячи маленьких файлов Parquet внутри раздела.

Вопрос или проблема

Я создаю набор данных Parquet, разделённый по двум столбцам. Он создаётся непосредственно из 30 000 txt-файлов (по 100 тысяч строк каждый), которые слишком велики, чтобы загружать в память сразу. Я действую следующим образом:

mydata <- open_dataset(
          sources = paste0(path_chunks,chunk_list), # вектор символов с путями к моим 30k .txt файлам
          format = "text",
          parse_options = parse_opts,               # просто некоторые опции, такие как разделитель и т.д.
          schema = myschema,                        # определяет типы моих столбцов с использованием arrow::schema()
          skip_rows = 0)

Я записываю набор данных следующим образом:

write_dataset(dataset = mydata,
              path = path_parquet,                  # путь к моей системе данных Parquet
              format = "parquet",
              partitioning = 
              c("country", "type"),                 # мои переменные разбиения
              compression = "snappy",
              use_dictionary = TRUE, 
              write_statistics = TRUE,
              min_rows_per_group = 5000000,         # использование памяти, не имеет отношения к размеру файла
              existing_data_behavior = "delete_matching")

Всё работает, я получаю набор данных Parquet, который могу запрашивать на основе моих подмножеств, и это удивительно быстро. Одна вещь, которая меня путает, это то, что внутри одного подмножества (например, “country == UK” и “type == A”) я могу иметь тысячи файлов Parquet. Первый файл большой (несколько гигабайт), а все остальные крошечные, обычно <100 килобайт. Мне кажется, что после первоначального сбора чего-то создаётся новый файл Parquet каждый раз, когда новый кусок из моих 30k кусков имеет такую комбинацию подмножества. Мои исходные данные в основном упорядочены по стране, но не идеально, так что это возможно. Поскольку arrow рекомендует гораздо более крупные файлы Parquet и меньше из них, я бы хотел иметь меньше больших файлов. Как я могу заставить это в конструкции файловой системы Parquet? Аргументы min/max row, похоже, не применимы, потому что (a) я не знаю, сколько строк в подмножестве у меня будет, поэтому не хочу устанавливать минимум (они могут быть крошечными), и (b) установка максимума, похоже, не является проблемой, потому что у меня получается тысячи крошечных файлов.

ps.: Если кто-то знает подходящий тег arrow для этого вопроса, пожалуйста, добавьте его, я не нахожу его.

Ответ или решение

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

Анализ проблемы

  1. Структура данных: Из вашего описания видно, что вы работаете с 30 тысячами текстовых файлов общего объема 100 тысяч строк каждый. Так как в памяти не удается загрузить все данные сразу, вы используете open_dataset() для поэтапного считывания данных.

  2. Настройки записи: Вы используете write_dataset() с параметрами, такими как partitioning, compression, и настройками для управления поведением с существующими данными. Ваша основная проблема заключается в создании множества мелких файлов, особенно в случаях, когда вы имеете большое количество подмножеств (например, комбинация "страна == UK" и "тип == A").

Основные причины появления мелких файлов

  • Несоответствие размеров и частоты создания:
    После обработки каждого из ваших 30 тысяч файлов может создаваться новый файл Parquet, если данные в этом файле не соответствуют ранее созданным файлам по колонкам "country" и "type". Это становится причиной большого количества мелких файлов, так как порядок данных не идеален.

  • Опции записи:
    Даже с установленным параметром min_rows_per_group, данные могут разбиваться на множество файлов, если ваша составленная выборка содержит меньшее количество строк.

Рекомендации по оптимизации

  1. Объединение данных перед записью:
    Постарайтесь консолидировать данные перед записью. Например, изучите возможность временного хранения данных в памяти при считывании нескольких файлов перед вызовом write_dataset(). Это может помочь увеличить размер создаваемых Parquet файлов.

  2. Изменение параметров:
    Попробуйте реализовать max_open_files или аналогичное. Это может ограничения на максимальное количество одновременно открытых файлов и может помочь объединить данные более эффективно.

  3. Использование параметра partitioning:
    Если ваши данные имеют естественные группы (например, по "country" или "type"), можно сначала сгруппировать данные и произвести запись для каждой группы отдельно. Это может помочь избежать создания мелких файлов в первую очередь.

  4. Оптимизация минимального и максимального числа строк:
    Хотя вы указали, что вам не известен объем данных, можно установить min_rows_per_group с разумным значением, которое, как вы предполагаете, должно обеспечивать некоторую эффективность.

    Если вы можете сделать оценку, например, основываясь на среднем количестве строк в ваших одномерных подмножествах — это даст возможность Arrow произвести более крупные файлы.

  5. Обратитесь к документации:
    Возможно, существуют обновлённые методы или параметры, доступные в более поздних версиях Arrow, которые позволят сделать о более гибким вариантом записи и управления Partition.

Заключение

Каждое из предложенных решений требует учёта и тестирования соответствия вашему случая. Понимание структуры данных и порядок обработки будут играть ключевую роль в создании более оптимального набора Parquet. Это приведет к уменьшению количества мелких файлов и улучшению общего управления пространством хранения и производительностью запросов.

Если у вас остаются вопросы или вам нужна дополнительная помощь по коду или данным, не стесняйтесь обратиться за помощью.

Оцените материал
Добавить комментарий

Капча загружается...