Мне нужно создать файл паркета, записывая части данных за раз, учитывая ограничения памяти. Пакет arrow
write_parquet
не поддерживает эту функциональность. Я понимаю, что могу писать в несколько файлов паркета и перечитывать их как «набор данных». Интересно, существуют ли альтернативные пакеты/решения для создания одного файла паркета. Последующие пользователи требуют этого. Python поддерживает добавление, но оно существенно портит поля даты и столбцы с плавающей запятой и не является вариантом.
Вот похожий вопрос на форуме Posit: forum.posit.co/t/appending-to-parquet-file-with-arrow/68383/3
У меня нет искрового кластера, а на моей единственной машине память является ограничением.
Действительно ли вам нужно добавить что-то к существующему файлу паркета или вам просто нужно создать новый файл паркета, написать немного, затем написать еще немного и т. д. и, наконец, закрыть все это в одном сеансе?
У меня недостаточно памяти для хранения всех данных. Буду читать по частям и записывать. Итак, добавление необходимо. Я знаю, что есть способ записывать фрагменты, но это мне не поможет, поскольку для начала все равно необходимо хранить все данные в памяти.
Запись файла паркета частями не требует, чтобы все данные находились в оперативной памяти одновременно.
Чтобы продемонстрировать это первое определение gen_data(i, size)
, которое создает фрейм данных с size
строками последовательно, начиная с i
, чтобы имитировать процесс, обсуждаемый в вопросе.
Теперь с помощью пакетаpeakRAM мы проверяем, сколько оперативной памяти требуется для создания кадра данных со строками 1e7 (76,3/макс. 152,6 МБ). Затем генерируйте одну десятую часть данных за раз и записывайте их в паркет в виде фрагмента, и в этом случае мы используем только 0,0/макс. 26,7 МБ. Это показывает, что нам не нужно было сразу хранить весь фрейм данных в оперативной памяти.
Ниже мы изменили источник write_parquet
в пакете стрелок, чтобы записывать данные частями.
library(arrow)
library(peakRAM)
invisible(gc())
gen_data <- function(i, size) {
data.frame(x = as.numeric(seq(i, length = size)))
}
f <- function() {
# define inputs
path <- "test.parquet"
# open
schema <- arrow_table(gen_data(1, 1))$schema # gen 1 row to get schema
sink <- FileOutputStream$create(path)
writer <- ParquetFileWriter$create(schema = schema, sink = sink,
properties = ParquetWriterProperties$create(names(schema)))
# writes
for(i in seq(1, 1e7, 1e6)) {
dat <- gen_data(i, 1e6)
writer$WriteTable(arrow_table(dat), chunk_size = 1e6)
gc()
}
# close
writer$Close()
sink$close()
}
Теперь проверьте это:
if (file.exists("test.parquet")) unlink("test.parquet")
invisible(gc())
peakRAM(gen_data(1, 1e7), f())
## Function_Call Elapsed_Time_sec Total_RAM_Used_MiB Peak_RAM_Used_MiB
## 1 gen_data(1,1e+07) 0.37 76.3 152.6
## 2 f() 1.78 0.0 26.7
Re: «Python поддерживает добавление», существует ли проблема с поведением, которое вы видите в трекере проблем Arrow (github.com/apache/arrow/issues)? Если действительно есть проблема, возможно, было бы хорошо ее исправить.