Pull to refresh

Comments 17

Один мой клиент в подобных случаях просто загонял этот огромный CSV в табличку в mysql и уже там делал все нужные выборки.
Почти всегда так делаю, когда нужно анализировать не очень большое кол-во данных.
Так и надо делать всегда. Индексы расставить и любая выборка в радость.
Лет 5 назад на собеседовании в nVidia мне задали подобный вопрос: "Как быстрее всего отсортировать данные из файла по определенному столбцу?". Я сразу сказал про реляционную БД и индексы. На что мне ответили: sort отрабатывает быстрее (а порой на много быстрее), чем перегонка данных в реляционную БД и последующая сортировка с выводом.
А собеседования я завалил, о чем, впрочем, не жалею.
Если нужно просто отсортировать один раз — то и смысла заморачиваться с БД нет. Смысл есть, если нужно сделать несколько разных выборок.
Судя по вопросу, размер файла никак не обговаривался. А я, скажем, легко себе представляю файлик, который sort вместе с ОС загонит в грустную задумчивость по причине задумчивости машины. Тогда как вариант с БД, как бы он не был монстрообразен, сработает, хотя, может быть, и долго проработает.
Любопытно, сколько ресурсов (времени на настройку и обработку, места, памяти) потребуется, чтобы построить индекс по этим данным с помощью специализированных средств. Например, загнать это все в elasticsearch.
Это определенно даст огромный выигрыш в анализе данных, но усложняет первоначальный процесс подготовки данных.
При наличии современного ноутбука достаточно легко поднимается производительная виртуалка с нужным стеком.
В случае ES потребуется только большой диск / либо разумное использование store: false, чтобы хранились только индексы, но не исходные данные. А так особых навыков не надо. Я спокойной загонял весь текстовый массив flibusta в эластик на ноуте с 16 гигами памяти и hdd дисками. Ну да, индекс занимал гигов 50-60 (при том что исходные данные весили 350 гиг).
> Количество файлов превышает допустимое и компьютер не всегда может их отслеживать. Многие инструменты Unix принимают только около 10,000 аргументов; использование звездочки в команде cat расширяет управление и передает 1,234,567 аргументов утилите. В итоге появляется сообщение об ошибке.

Мне кажется тут автор слабо понимает, что вообще происходит в системе. Звёдочка при таком подходе используется не в cat, а в вашем шелле. Который звёздочку раскрывает и вызывает утилиту (полезно отличать внешние утилиты от встроенных команд шелла) cat с множеством аргументов. Убедиться для наглядности можно так:
cat * /proc/self/cmdline
При этом упираемся в предел максимальной длины аргументов, которые может ядро передать процессу. Посмотреть предел:
$ getconf ARG_MAX
524288
Это в байтах. ЕМНИП, выставляется он при компиляции ядра. Строки аргументов передаются в одном массиве, разделённом нулями (см. /proc/$PID/cmdline), при этом стоит иметь ввиду, что в ARG_MAX должны вписаться не только параметры командной строки, но и переменные окружения + ещё мелочи.

> for f in *; do cat «$f» >> ../transactions_cat/transactions.csv; done
Это ужасно. На каждый файл запускается свой экземпляр утилиты cat. Запуск нового процесса довольно дорогая операция, какой бы он ни был простой и маложрущий, не стоит ожидать, что система сможет запускать больше ~1000 процессов в секунду (на одном ядре).

> ls | parallel -m -j $f «cat {} >> ../transactions_cat/transactions.csv»
Знаете что у вас тут тормозит? ls :) Не забываем, что ls при вызове без аргументов сортирует вывод, а сложность сортировки n*log(n) и на миллионе файлов она становится медленной и печальной. Но можно сказать ls не заниматься лишней работой с сортировкой:
ls -U
Кстати, проблема с сортировкой есть и при использовании * шелла

Но вообще всё это фигня. Нужно просто вызвать несколько раз cat передав ему максимум аргментов, сколько можно передать за раз. Результат конечно зависит от средней длины имени файла, но можно легко ожидать, что один вызов cat приведёт к выводу примерно 1000 файлов. И ускорение будет значительно.
find -type f -exec cat {} +
Магия в использовании +

ЗЫ: а зачем вообще нестандартный parallel, если стандартный xargs умеет --max-procs и --max-args?
Тот самый момент когда комментарии ценнее поста.
Скажите, в чем магия использования "+"?
Для шелла + не несёт специального значения (если не внутри особых случаев, вроде арифметики $(( var+5)) ) и передаётся как есть аргументом запускаемому find.
Action -exec у find требует после терминировать список аргументов запускаемой команды. Это можно сделать либо с помощью аргумента ';', либо с помощью '+'. Поведение отличается: с плюсом запускаемой команде в аргументах будет передаваться по нескольку файлов, сколько влезает в ARG_MAX. См. man find

>Тот самый момент когда комментарии ценнее поста.
комментарий при этом получает +9, а карма автора комментария — -2. Типичный хабр.
Спасибо, тоже не знал про "+", хотя саму команду часто использую!
А карму вам нельзя поднять, т.к. статей нет (можно только опускать) :)
ls | parallel -m -j $f «cat {} >> ../transactions_cat/transactions.csv»

Даже удивительно, что это команда у вас отработала нормально. Стандартные потоки вывода разных экземпляров cat смешаются и получиться некорректный файл. И проблема не в том, что строки будут переставлены местами, а в том что из
test1,test2,test3

и
abc1,abc2,abc3

получится
test1,test2,abc1,abc2,abc3
test3
Интересно было бы Spark-ом попробовать. Ваши выборки, на первый взгляд, хорошо ложатся и не нужно в один файл сливать перед обработкой.
Что за бред я сейчас прочитал? Что это за ненормальный магазин, который сразу не хранит продажи в базе данных, откуда их потом можно как угодно сгруппировать, например с помощью SELECT xx WITH ROLLUP
Ну так и не надо тогда упоминать слово «магазин» и «транзакции» в тексте.
Sign up to leave a comment.