Подтвердить что ты не робот

Нужен способ сортировки файла журнала на 100 ГБ по дате

Итак, по какой-то странной причине я заканчиваю файл журнала размером 100 ГБ, который является несортированным (на самом деле он частично отсортирован), в то время как для алгоритмов, которые я пытаюсь применить, требуются отсортированные данные. Строка в файле журнала выглядит так

data <date> data data more data

У меня есть доступ к С# 4.0 и около 4 ГБ ОЗУ на моей рабочей станции. Я бы предположил, что какой-то вид слияния будет лучше всего, но не до конца реализовать эти алгоритмы - я хочу спросить, есть ли какой-нибудь ярлык, который я мог бы сделать.

Кстати, синтаксический анализ строки даты с помощью DateTime.Parse() очень медленный и занимает много процессорного времени. Скорость прерывания составляет 10 МБ/с. Есть ли более быстрый способ, чем следующий?

    public static DateTime Parse(string data)
    {            
        int year, month, day;

        int.TryParse(data.Substring(0, 4), out year);
        int.TryParse(data.Substring(5, 2), out month);
        int.TryParse(data.Substring(8, 2), out day);

        return new DateTime(year, month, day);
    }

Я написал, что для ускорения DateTime.Parse() и он действительно работает хорошо, но по-прежнему берет нагрузку на циклы циклов.

Обратите внимание, что для текущего лог файла меня интересуют часы, минуты и секунды. Я знаю, что я могу предоставить DateTime.Parse() с форматом, но это, похоже, не ускоряет его.

Я ищу подталкивание в правильном направлении, спасибо заранее.

EDIT. Некоторые люди предположили, что я использую сравнение строк, чтобы сравнивать даты. Это будет работать для этапа сортировки, но мне нужно разобрать даты для алгоритмов. Я до сих пор не знаю, как сортировать файл 100 ГБ на 4 ГБ свободного бара, не делая его вручную.

EDIT 2. Хорошо, благодаря нескольким предложениям, которые я использую сортировку окон, я узнал, что есть аналогичный инструмент для Linux. В основном вы вызываете сортировку, и она исправляет все для вас. Когда мы говорим, что это что-то делает, и я надеюсь, что скоро это закончится. Команда, которую я использую,

sort -k 2b 2008.log > 2008.sorted.log

-k указывает, что я хочу сортировать во второй строке, которая является строкой даты в обычном формате YYYY-MM-DD hh:mm:ss.msek. Должен признать, что man-страницы не объясняют все варианты, но я нашел много примеров, запустив info coreutils 'sort invocation'.

Я отчитаю результаты и тайминги. Эта часть журнала составляет около 27 ГБ. Я думаю о сортировке в 2009 и 2010 годах отдельно, а затем слияние результатов в один файл с параметром sort -m.

Изменить 3 Ну, проверяя iotop, он предлагает, чтобы он читал небольшие куски файла данных, а затем яростно занимаясь чем-то, чтобы обработать их. Этот процесс кажется довольно медленным. = (

sort не использует память и только одно ядро. Когда он считывает данные с диска, он ничего не обрабатывает. Я что-то делаю неправильно?

Изменить 4 Три часа, и он по-прежнему делает то же самое. Теперь я нахожусь на том этапе, где я хочу попробовать играть с параметрами функции, но я потратил три часа... Я остановлюсь примерно через 4 часа и постараюсь поместить его на ночь вычисления с умной памятью и пространственные параметры...

Изменить 5. Прежде чем я вернулся домой, я перезапустил процесс с помощью следующей команды:

sort -k 2b --buffer-size=60% -T ~/temp/ -T "/media/My Passport" 2010.log -o 2010.sorted.log

Он вернулся сегодня утром:

sort: write failed: /media/My Passport/sortQAUKdT: File too large

Wraawr! Я думал, что просто добавлю как можно больше жестких дисков, чтобы ускорить этот процесс. Судя по всему, добавление USB-накопителя было наихудшей идеей. На данный момент я не могу даже сказать, касается ли это FAT/NTFS или некоторых таких, потому что fdisk говорит мне, что USB-накопитель является "неправильным устройством"... не шутит. Я постараюсь дать ему еще один шаг позже, а теперь пусть этот проект попадет в неудачную кучу.

Заключительное уведомление На этот раз он работал с той же командой, что и выше, но без проблемного внешнего жесткого диска. Спасибо всем за вашу помощь!

Бенчмаркинг

Используя 2 жестких диска с памятью (минимум 70 Мбит/с IO) на одном и том же контроллере SATA, мне потребовалось 162 минуты, чтобы отсортировать файл журнала 30 ГБ. Мне нужно будет отсортировать еще 52 ГБ файла сегодня, я опубликую, как это происходит.

4b9b3361

Ответ 1

Если для вас будет работать сортировка строк, просто используйте команду Windows SORT. Сортируйте файл и делайте с ним. Он с удовольствием отсортирует ваш 100GB файл и прост в использовании.

Если вам нужно отфильтровать и преобразовать файл, в частности поле даты, я просто напишу небольшую программу конверсии, которая преобразует поле данных в число, заполненное 0 (например, количество секунд с 1970 года или все, что вам нравится ) и перезаписывает запись. Затем вы можете передать (|) вывод в команду сортировки, тогда у вас есть окончательный, отсортированный файл, который более легко анализируется вашей служебной программой.

Я думаю, что ошибка, которую вы делаете, просто пытается сделать это за один раз. 100 ГБ данных очень много, и для копирования требуется некоторое время, но это не займет много времени. Поскольку вам нужно его сортировать, вам уже придется иметь дело с копией файла в какой-то момент (т.е. Вам нужно столько свободного места на вашем компьютере, чтобы обрабатывать обе копии в какое-то время), даже с внешней процедурой сортировки, такой как сортировка слияния.

Написание простого риформайтера и его подключение к сортировке позволит вам сэкономить пару попыток через файл и сэкономить место на диске, поскольку вам неизбежно потребуются две копии.

Я бы также подстроил форматировщик, чтобы вытащить только те поля, которые мне действительно интересны, и делать все "тяжелые" синтаксические разборки в этой точке, так что то, что вы заканчиваете, по существу является форматированным файлом, который легко обрабатывается ваши процедуры отчетности. Таким образом, вы сэкономите время позже, когда потенциально запускаете свои отчеты более одного раза.

Используйте простой CSV или, что еще лучше, формат файла фиксированной длины для вывода, если это возможно.

Убедитесь, что ваша информация о дате, если вы решите использовать целое число, имеет все поля одинаковой длины. В противном случае утилита SORT не будет сортировать их правильно (в итоге вы получите 1 10 2 3 вместо 1 2 3 10. Лучше иметь 01 02 03 10.).

Изменить -

Подходите к нему с другого такта.

Самый большой вопрос: "нужны ли вам все эти данные". Это связано с более ранним предложением о начале сильного анализа. Очевидно, чем больше вы можете уменьшить начальный набор, тем лучше. Например, просто удаление 10% данных - 10 ГБ.

Что-то, о чем мне нравится думать, как правило, особенно при работе с большим количеством данных: "Если у вас есть 1 миллион чего-то, то каждая миллисекунда сохраняется, составляет 20 минут от нижней строки".

Обычно мы действительно не думаем о миллисекундах для нашей работы, это больше "место штанов", "это чувствует себя быстрее". Но 1 мс == 20мин/миллион - хорошая мера, чтобы понять, сколько данных вы имеете в виду, и как долго материал должен/мог бы принимать.

Для вас случай, 100 ГБ данных. С записью 100 байт на запись вы берете 1 миллиард строк. 20 000 минут в миллисекунду. - 5 1/2 часа. gulp (Это эмпирическое правило, если вы делаете математику, это не совсем подходит для этого.)

Итак, вы можете оценить желание уменьшить необработанные данные, если это вообще возможно.

Это была одна из причин, по которой я отложил команду Windows SORT. Это основной процесс, но на него влияет нюанс, и тот, который может использовать некоторую оптимизацию. Люди, которые писали СОРТ, имели время и возможность сделать его "оптимальным" во многих отношениях. Были ли они или нет, я не могу сказать. Но его справедливое предположение, что они будут уделять больше времени и внимания этому процессу, чтобы сделать их СОРТ столь же практичным, как и вы, находящиеся в сжатом сроке.

Существуют сторонние утилиты сортировки для больших наборов данных, которые, вероятно (в идеале) работают лучше для этого случая. Но, они недоступны для вас (вы можете получить их, но я не думаю, что вы хотели спешить и получить другую полезность сразу). Итак, SORT - это наше лучшее предположение.

Тем не менее, сокращение набора данных будет больше, чем любая утилита.

Сколько вам нужно? И сколько информации вы действительно отслеживаете? Например, если бы это была, скажем, веб-статистика, у вас может быть 1000 страниц на вашем сайте. Но даже с почасовыми цифрами за год 365 * 24 * 1000, что только 8,7 М "ведра" информации - далеко от 1В.

Итак, есть ли какая-либо предварительная обработка, которую вы можете сделать, которая не требует сортировки? Обобщение информации в более грубую детализацию? Вы можете сделать это без сортировки, просто используя хэш-карты на основе памяти. Даже если у вас нет "достаточной памяти" для обработки всех 100 ГБ данных за один бросок, вам, вероятно, достаточно сделать это в кусках (5 кусков, 10 кусков) и выписать промежуточные результаты.

У вас также может быть намного лучшая удача, расщепляющая данные. В месячные или еженедельные фрагменты файлов. Возможно, это непросто сделать, потому что данные "в основном" сортируются. Но в этом случае, если по дате, правонарушители (т.е. Данные, которые не сортируются) вполне могут быть сгруппированы внутри файла, причем материал "не в порядке" просто смешивается с барьерами временных периодов ( например, около дневных переходов, может быть, у вас есть такие строки, как 11:58 вечера, 11:59 вечера, 00:00, 00:01, 23:58, 00:02 вечера). Возможно, вы также сможете использовать эту эвристику.

Цель состоит в том, что если вы можете несколько детерминистически определить подмножество, которое не соответствует порядку, и разбить файл на куски "в порядке данных" и "данные не в порядке", ваша задача сортировки может быть МНОГО МНОГО меньше, Сортируйте несколько строк, которые не соответствуют порядку, а затем у вас проблема слияния (гораздо проще, чем проблема сортировки).

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

Ответ 2

Код, подобный этому, полностью связан с тем, как быстро вы можете получить данные с диска. Файл просто никогда не может вписаться в кеш файловой системы, поэтому вы всегда ждете на диске, чтобы предоставить данные. Вы достаточно хорошо справляетесь со скоростью 10 МБ/с, оптимизация кода никогда не будет иметь заметного эффекта.

Получить более быстрый диск. Дефрагментируйте тот, который у вас есть как промежуточный шаг.

Ответ 3

Короткий ответ - загрузите данные в реляционную базу данных, например, Sql Express, создайте индекс и используйте решение на основе курсора, например DataReader, чтобы прочитать каждую запись и записать ее на диск.

Ответ 4

Чтобы ответить на ваш вопрос о сортировке длинного файла, который не вписывается в память, вам потребуется использовать внешнюю сортировку алгоритм, такой как сортировка слияния. Процесс примерно следующий:

  • Разделите вход на несколько частей, которые вписываются в память и могут быть отсортированы с использованием стандартных алгоритмов сортировки в памяти (например, 100 МБ или больше - вам нужно будет хранить ~ 4 части в памяти сразу). Отсортируйте все детали и запишите их на диск.

  • Прочитайте две части с диска (они оба отсортированы) и объедините их, что можно сделать, просто одновременно итерации по двум входам. Напишите объединенный набор данных в другое место на диске. Обратите внимание, что вам не нужно читать всю деталь в памяти - просто прочитайте ее/напишите ее в блоках по ходу.

  • Повторите слияние частей, пока у вас не будет только одна часть (которая будет сортироваться со всеми данными из вашего исходного набора входных данных).

Вы упомянули, что данные уже частично отсортированы, поэтому было бы неплохо выбрать некоторый алгоритм для сортировки в памяти (на первом этапе), который является эффективным в этом случае. Вы можете увидеть некоторые предложения в этом вопросе (хотя я не уверен, будет ли ответ одинаковым для очень больших наборов данных - и это зависит от того, сколько частично отсортировано вход есть).

Ответ 5

Почему бы вам не попробовать этот относительно нестандартный инструмент из microsoft, называемый logparser. Это в основном позволяет вам выполнять SQL-запрос через файл CSV (или любой другой форматированный текстовый файл).

Сохраняет проблемы с перекачкой его в базу данных, делает ваш вид и откачивает его обратно

Ответ 6

Лучший способ оптимизации синтаксического анализа дат - не анализировать их вообще.

Как даты в формате ISO 8601, вы можете просто сравнить их как строки. Отсутствует никакой синтаксический анализ.

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

Другой подход может состоять в том, чтобы прочитать файл и записать записи, которые упорядочены в один файл, а другие - в другой файл. Сортируйте второй файл (возможно, используя этот процесс рекурсивно, если он большой) и заархивируйте два файла вместе. То есть измененная сортировка слияния.

Ответ 7

Для сортировки вы можете реализовать сортировку ведра на основе файлов:

  • Открыть входной файл
  • Прочитать файл по строкам
  • Получить дату как строку из строки
  • Добавить строку в файл <date>.log

Результатом будет отдельный файл журнала для каждого дня или отдельный для каждого часа. Выберите так, чтобы вы получали файлы размером, который вы можете легко отсортировать.

Остальная задача - сортировать созданные файлы и, возможно, снова объединить файл.

Ответ 8

Мне нужно проанализировать даты для алгоритмов.

В * NIX я обычно должен был сначала преобразовать даты в нечто простое, подходящее для сравнения текста и сделанное им первое слово в строке. Это слишком рано для создания даты/времени. Моя обычная дата-презентация YYYYMMDD-hhmmss.millis. Сделайте так, чтобы все файлы имели одинаковый формат даты.

Я до сих пор не знаю, как сортировать файл 100 ГБ на 4 ГБ свободного бара, не делая его вручную.

Как вы уже поняли, сортировка слияния является единственной опцией.

Итак, для меня задачи относятся к следующему шагу:

  • Неверное преобразование для сортировки дат. Сложность: чтение/запись последовательно 100 ГБ.

  • разделяет данные в кусках полезного размера, например. 1 ГБ и сортировать каждый фрагмент, используя простой быстрый вид, прежде чем записывать его на диск. Сложность: чтение/запись последовательно 100 ГБ; память для быстрого сортировки.

  • merge-сортировать небольшие файлы в один большой. Можно сделать это пошагово, используя программу, которая берет два файла и объединяет их в новую. Сложность: чтение/запись последовательно 100 ГБ log (N) раз (где N - количество файлов). Требования к пространству на жестком диске: 2 * 100 ГБ (последнее слияние файлов размером 2 х 50 ГБ в один файл размером 100 ГБ).

  • Программа для автоматизации предыдущего шага: выберите два (например, самые маленькие) файлы, запустите программу для сортировки-слияния их в новый файл, удалите два оригинальных файла. Повторяйте до тех пор, пока количество файлов больше 1.

  • (Необязательно) разбить отсортированный файл на 100 ГБ на более мелкие куски управляемого размера. В конце концов вы собираетесь с ними что-то сделать. Выполните их последовательно или поместите в файл имя и фамилию последнего и последнего времени.

Общая концепция: не пытайтесь найти способ сделать это быстро, трубопровод 100GB потребует времени в любом случае; планируйте программы на каждом шагу, чтобы работать в течение ночи в качестве партии, без вашего внимания.

В Linux, который можно использовать с оболочкой /sort/awk/Perl, и я не думаю, что это проблема, чтобы написать все это на любом другом языке программирования. Это потенциально 4 программы, но все они довольно просты для кодирования.

Ответ 9

Предполагая, что ваш файл журнала содержит только 1-2% строк, вы можете сделать один проход через полный журнал, выводя два файла: один файл в порядке и другой файл, содержащий 1-2 % строк, которые не соответствуют порядку. Затем отсортируйте строки вне порядка в памяти и выполните одно слияние ранее не упорядоченных строк со строками в порядке. Это будет намного быстрее, чем полный слияние, которое будет делать еще много проходов.

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

Ответ 10

На самом деле у меня нет много идей о преобразовании даты, но то, что я попытаюсь использовать для этого:

  • База данных с индексом в столбце даты (для удобства поиска в этих данных после).
  • Вставить в эту базу используйте Bulk Insert.
  • И какой-то способ параллельного чтения (в параллельном примере LINQ будет хорошим и очень простым в использовании).
  • Много терпения (самая важная/трудная вещь)

Ответ 11

Упреждающий комментарий: в моем ответе рассматривается только подзадача значений времени синтаксического анализа.

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

class DateParserYyyyMmDd
{
    static void Main(string[] args)
    {
        string data = "2010-04-22";

        DateTime date = Parse(data);
    }

    struct Date
    {
        public int year;
        public int month;
        public int day;
    }

    static Date MyDate;

    static DateTime Parse2(string data)
    {
        MyDate.year = (data[0] - '0') * 1000 + (data[1] - '0') * 100 
            + (data[2] - '0') * 10 + (data[3] - '0');
        MyDate.month = (data[5] - '0') * 10 + (data[6] - '0');
        MyDate.day = (data[8] - '0') * 10 + (data[9] - '0');

        return new DateTime(MyDate.year, MyDate.month, MyDate.day);
    }
}

Ответ 12

Помимо того, что вы делаете (возможно, подсказка будет полезна), ваш синтаксический анализ может быть выполнен по нескольким потокам, если у вас есть несколько процессоров или процессорных ядер.

Ответ 13

Вы можете попробовать реализовать алгоритм сортировки radix. Поскольку radix сканирует весь список последовательно и только несколько раз, он может помочь здесь предотвратить гигантское количество сканирований и попыток вашего 100-гигабайтного файла.

Radix sort намеревается классифицировать ваши записи каждую итерацию одной частью. Эта часть может быть цифрой или частью datetime, например, годом, месяцем, днем. в этом случае вам даже не нужно преобразовывать строку в DateTime, вы можете преобразовать только определенную часть в int.

Edit:

Для сортировки вы можете создать двоичный файл temp только с двумя столбцами: DateTime (DateTime.ToBinary() как Int64) и адрес строки в исходном файле (как Int64).

Затем вы получаете гораздо меньший файл с фиксированными записями размера, всего 16 байт на запись, тогда вы можете сортировать его намного быстрее (операции ввода-вывода будут быстрее, по крайней мере).

После завершения сортировки временного файла вы можете создать полный файл журнала с сортировкой 100 ГБ.

Ответ 14

Не совсем как решение, а просто из интереса, один из способов сделать это вот так:

  • Сначала распакуйте файл в 1GB файлы.
  • Затем чтение 2 файлов за раз, загрузка содержимого в список строк и сортировка его
  • Запишите его обратно в отдельные файлы.

Проблема в том, что вам нужно будет прочитать/записать 100 файлов на каждом проходе и выполнить 100 проходов, чтобы убедиться, что данные отсортированы.

Если моя математика правильная: это 10 000 ГБ и 10 000 ГБ, в среднем 10 МБ/с, что составляет 20 000 000 сек, что составляет 231 дней

Один из способов работы может заключаться в том, что вы сканируете файл один раз и записываете файлы меньшего размера, по одному для каждого периода времени, например, дня или часа. Затем отсортируйте эти отдельные файлы.

Ответ 15

Ого. Прежде всего, это совершенно новый уровень документирования-одержимости.

Мое фактическое устройство было бы, попробуйте рассмотреть, как этот файл действительно нужен.

О сортировке, я понятия не имею, будет ли это работать или нет, но вы можете попытаться создать Enumerator, который возвращает данные непосредственно с жесткого диска (возможно, не сохраняет ничего, кроме нескольких указателей), а затем пытается используйте LINQ OrderBy, который также возвращает IEnumerator, который, надеюсь, может Enamurate и сохранить непосредственно обратно на диск.

Вопрос только в том, сохраняет ли OrderBy что-либо в ОЗУ.

Ответ 16

Загрузите вкус Linux с USB И используйте команду while для чтения Файл. Используйте grep, фильтры и Трубы для разделения данных. Все это можно сделать в 3 строки BASH script. Греп будет копировать данные в Нет времени. Я прошел через 7 миллионов строк за 45 секунд