фильтрация журнала почтового сервера - PullRequest
0 голосов
/ 27 марта 2011

У меня есть файл журнала почтового сервера размером в несколько ГБ и список идентификаторов сообщений ~ 350k.Я хочу вытащить из большого файла журнала строки с идентификаторами из длинного списка ... и я хочу, чтобы это было быстрее, чем сейчас ... В настоящее время я делаю это в perl:

#!/usr/bin/perl

use warnings;

#opening file with the list - over 350k unique ID
open ID, maillog_id;
@lista_id = <ID>;
close ID;
chomp @lista_id;

open LOG, maillog;
# while - foreach would cause out of memory
while ( <LOG> ) {
        $wiersz = $_;
        my @wiersz_split = split ( ' ' , $wiersz );
        #
        foreach ( @lista_id ) {
          $id   = $_;
          # ID in maillog is 6th column
          if ( $wiersz_split[5] eq $id)  {
            # print whole row when matched - can be STDOUT or file or anything
            print "@wiersz_split\n";
          }
        }
}
close LOG;

Это работаетно это медленно ... Каждая строка из журнала берется в сравнение со списком ID.Должен ли я использовать базу данных и выполнить своего рода соединение?Или сравнить подстроки?

Существует множество инструментов для анализа логов - например, pflogsumm ... но это просто суммирует.Например, я мог бы использовать

grep -c "status=sent" maillog

Это было бы быстро, но бесполезно, и я бы использовал его ПОСЛЕ фильтрации моего файла журнала ... То же самое для pflogsumm и т. Д. - просто увеличивая переменные.

Есть предложения?

-------------------- ОБНОВЛЕНИЕ -------------------

спасибо Dallaylaen, мне это удалось (вместо внутреннего foreach на @lista_id):

if ( exists $lista_id_hash{$wiersz_split[5]} ) { print "$wiersz"; }

где %lista_id_hash - хеш-таблица, где ключи - это элементы, взятые из моего списка идентификаторов.Это работает очень быстро.Обработка 4,6 ГБ файла журнала с> 350k идентификаторами занимает менее 1 минуты для фильтрации интересных журналов.

1 Ответ

2 голосов
/ 27 марта 2011

Используйте хэш.

my %known;
$known{$_} = 1 for @lista_id;
# ...
while (<>) {
    # ... determine id
    if ($known{$id}) {
         # process line
    };
};

P.S. Если ваш журнал очень большой, вам, вероятно, лучше разбить его, например, на: последние две буквы $ id в 256 (или 36 ** 2?) меньших файлах. Что-то вроде MapReduce для бедного человека. Количество идентификаторов, сохраняемых в памяти за один раз, также будет уменьшено (т. Е. Когда вы обрабатываете maillog.split.cf, вы должны хранить только идентификаторы, оканчивающиеся на «cf» в хэше).

...