Вопрос или проблема
Я создаю набор данных 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, разбитый на два столбца, и сталкиваетесь с количеством мелких файлов, что не является оптимальным с точки зрения производительности и хранения. Давайте детально рассмотрим ваши шаги и предложим возможные решения.
Анализ проблемы
-
Структура данных: Из вашего описания видно, что вы работаете с 30 тысячами текстовых файлов общего объема 100 тысяч строк каждый. Так как в памяти не удается загрузить все данные сразу, вы используете
open_dataset()
для поэтапного считывания данных. -
Настройки записи: Вы используете
write_dataset()
с параметрами, такими какpartitioning
,compression
, и настройками для управления поведением с существующими данными. Ваша основная проблема заключается в создании множества мелких файлов, особенно в случаях, когда вы имеете большое количество подмножеств (например, комбинация "страна == UK" и "тип == A").
Основные причины появления мелких файлов
-
Несоответствие размеров и частоты создания:
После обработки каждого из ваших 30 тысяч файлов может создаваться новый файл Parquet, если данные в этом файле не соответствуют ранее созданным файлам по колонкам "country" и "type". Это становится причиной большого количества мелких файлов, так как порядок данных не идеален. -
Опции записи:
Даже с установленным параметромmin_rows_per_group
, данные могут разбиваться на множество файлов, если ваша составленная выборка содержит меньшее количество строк.
Рекомендации по оптимизации
-
Объединение данных перед записью:
Постарайтесь консолидировать данные перед записью. Например, изучите возможность временного хранения данных в памяти при считывании нескольких файлов перед вызовомwrite_dataset()
. Это может помочь увеличить размер создаваемых Parquet файлов. -
Изменение параметров:
Попробуйте реализоватьmax_open_files
или аналогичное. Это может ограничения на максимальное количество одновременно открытых файлов и может помочь объединить данные более эффективно. -
Использование параметра
partitioning
:
Если ваши данные имеют естественные группы (например, по "country" или "type"), можно сначала сгруппировать данные и произвести запись для каждой группы отдельно. Это может помочь избежать создания мелких файлов в первую очередь. -
Оптимизация минимального и максимального числа строк:
Хотя вы указали, что вам не известен объем данных, можно установитьmin_rows_per_group
с разумным значением, которое, как вы предполагаете, должно обеспечивать некоторую эффективность.Если вы можете сделать оценку, например, основываясь на среднем количестве строк в ваших одномерных подмножествах — это даст возможность Arrow произвести более крупные файлы.
-
Обратитесь к документации:
Возможно, существуют обновлённые методы или параметры, доступные в более поздних версиях Arrow, которые позволят сделать о более гибким вариантом записи и управления Partition.
Заключение
Каждое из предложенных решений требует учёта и тестирования соответствия вашему случая. Понимание структуры данных и порядок обработки будут играть ключевую роль в создании более оптимального набора Parquet. Это приведет к уменьшению количества мелких файлов и улучшению общего управления пространством хранения и производительностью запросов.
Если у вас остаются вопросы или вам нужна дополнительная помощь по коду или данным, не стесняйтесь обратиться за помощью.