我有多GB邮件服务器日志文件和~350k邮件ID列表。 我想从长列表中删除带有ID的大日志文件行......我希望它比现在更快... 目前我在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等 - 只是增加变量。
有什么建议吗?
-------------------- UPDATE -------------------
谢谢Dallaylaen,
我成功了(而不是@lista_id
上的内部foreach:
if ( exists $lista_id_hash{$wiersz_split[5]} ) { print "$wiersz"; }
其中%lista_id_hash
是一个哈希表,其中键是从我的ID列表中获取的项目。它的工作速度非常快。
使用&gt; 350k ID处理4,6 GB日志文件只需不到1分钟即可过滤有趣的日志。
答案 0 :(得分:2)
使用哈希。
my %known;
$known{$_} = 1 for @lista_id;
# ...
while (<>) {
# ... determine id
if ($known{$id}) {
# process line
};
};
P.S。如果您的日志很大,那么根据例如你的日志分割它可能会更好。将$ id的最后两个字母分成256(或36 ** 2?)个较小的文件。有点像穷人的MapReduce。一次存储在内存中的ID数量也将减少(即,当您处理maillog.split.cf时,您应该只保留以散列中的“cf”结尾的ID。)