Разделение больших файлов пополам - PullRequest
1 голос
/ 13 апреля 2019

tl; dr: Мне нужен способ разделения файлов строк размером 5 ГБ / ~ 11м пополам (или третями), сохраняя при этом отслеживание точно каждого файла, который я создаю, и, конечно, не прерывая строки, так что я могу обрабатывать оба файла одновременно

У меня есть набор из 300 очень больших json-подобных файлов, которые мне нужно периодически анализировать с помощью php-скрипта. Каждый файл около 5 ГБ распакован. Я чертовски оптимизировал скрипт разбора, и он достиг ограничения скорости. Но это все еще однопоточный сценарий, работающий около 16 часов на 16-ядерном сервере.

Я бы хотел разделить каждый файл примерно на половину и запустить сразу два сценария синтаксического анализа, чтобы «подделать» многопоточность и ускорить время выполнения. Я могу хранить глобальную информацию о времени выполнения и "сообщения" между потоками в моей базе данных SQL. Это должно сократить общее время выполнения вдвое: один поток загружает файлы, другой распаковывает их, а два других загружают их в sql параллельно.

Эта часть на самом деле довольно прямолинейна, и я застрял, разбивая файл для анализа. Я знаю, что есть split инструмент, который может разбивать файлы на куски на основе КБ или количества строк. Проблема в том, что это не совсем работает для меня. Мне нужно аккуратно разделить эти файлы пополам (или трети или четверти). И без лишних данных перейдите в дополнительный файл. Мне нужно точно знать, какие файлы создала команда split, чтобы я мог отметить файл easy в моей таблице sql, чтобы скрипт синтаксического анализа мог знать, какие файлы готовы для анализа. Если возможно, я бы даже хотел избежать запуска wc -l в этом процессе. Это может быть невозможно, но для каждого файла требуется около 7 секунд, 200 файлов, что означает 35 дополнительных минут времени выполнения.

Несмотря на то, что я только что сказал, я предполагаю, что я запускаю wc -l file в моем файле, делим это на n , округляем результат до и используем split, чтобы разбить файл на столько строк Это всегда должно дать мне ровно n файлов. Чем я могу просто знать, что у меня есть filea, fileb и так далее.

Полагаю, в конечном итоге вопрос в том, есть ли лучший способ справиться с этой проблемой? Может быть, есть еще одна утилита, которая разделится таким образом, чтобы она была более совместима с тем, что я делаю. Или, может быть, есть другой подход, который я полностью игнорирую.

1 Ответ

1 голос
/ 13 апреля 2019

У меня была такая же проблема, и было нелегко найти решение.

Сначала вам нужно использовать jq для преобразования JSON в строковый формат.

Затем используйте версию GNU split, у нее есть дополнительная опция --filter, которая позволяет обрабатывать отдельные фрагменты данных в гораздо меньшем пространстве, поскольку не требуется создавать временные файлы:

split --filter='shell_command'

Ваша команда фильтра должна читать из stdin:

jq -r '' file.json | split -l 10000 --filter='php process.php'

-l скажет split работать на 10000 строк одновременно.

В process.php файле, который вам просто нужно читайте со стандартного ввода и делайте что хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...