web-dev-qa-db-ja.com

巨大なファイルをgrepするパフォーマンスを改善する

300,000行を超えるFILE_Aと3,000万行を超えるFILE_Bがあります。 FILE_BでFILE_Aの各行を調べ、grepの結果を新しいファイルに書き込む Bash スクリプトを作成しました。

このプロセス全体に5時間以上かかります。

スクリプトのパフォーマンスを向上させるにはどうすればよいですか?

grep -F -m 1をgrepコマンドとして使用しています。 FILE_Aは次のようになります。

123456789 
123455321

fILE_Bは次のようになります。

123456789,123456789,730025400149993,
123455321,123455321,730025400126097,

したがって、Bashを使用すると、FILE_Aの次の行を選択してFILE_Bでそれを把握するwhileループがあります。パターンがFILE_Bで見つかったら、result.txtファイルに書き込みます。

while read -r line; do
   grep -F -m1 $line 30MFile
done < 300KFile
10
rogerio_marcio

grep --file==FILE_Aを使用してみてください。ほとんどの場合、パターンをメモリにロードします。つまり、FILE_Bを1回だけスキャンします。

grep -F -m1 --file==300KFile 30MFile
17
Gort the Robot

これが後世のための Perl 答えです。 100万行から3億-3千5百万行を一致させるために、これを定期的に行います。完了するまでに約10秒かかります。

まず、FILE_Aをハッシュ化します。

my %simple_hash;
open my $first_file, '<', 'FILE_A' or die "What have you done?! $!";
while (<$first_file>) {
  chomp;                 ## Watch out for Windows newlines
  $simple_hash{$_} = 1;  ## There may be an even faster way to define this
}
close $first_file;

次に、大きなファイルが区切られていて、その後に続く列がわかっている場合は、FILE_Bを実行するときに、ハッシュキーの存在のみを確認します。これは、です。 等しいか正規表現の一致をチェックするよりも高速:

open my $second_file, '<', 'FILE_B' or die "Oh no, not again.. $!";
while (<$second_file>) {
  my ($col1, undef) = split ',';
  if (exists($simple_hash{$col1}) {
    print $_;
  }
}
close $second_file;

大きなターゲットファイルがうまく解析できない場合、このスクリプトはその値を失います。速度の大部分は 正規表現 エンジンを起動する必要がないためです。

2
Mintx

さらに複雑なプログラミングを気にしない場合は、 suffix trees (またはバリアント)の使用を検討してください。

FILE_Bは、線形時間で kkonenのアルゴリズム を使用して前処理できます。次に、FILE_Aの各行を時間の長さで線形にクエリし、一致するすべての行番号を取得します(ツリーを少し調整する必要がある場合があります)。これを結果ファイルに書き込むことができます。

NがFILE_Bの長さであり、NFILE_Aの行数であり、mが最も長い行の長さである場合、プロシージャ全体が時間O(n + Nm)で実行されます。 in FILE_A-これは基本的に線形ランタイムです。元のアプローチに必要な2次時間を大幅に上回ります。

1
Raphael

最近--mmapフラグを見つけましたが、テストする機会がありませんでしたが、調査結果について喜んでお知らせいたします。これはmanページの説明です:

--mmap If  possible, use the mmap(2) system call to read input, instead
      of the default read(2) system call.  In some situations,  --mmap
      yields  better performance.  However, --mmap can cause undefined
      behavior (including core dumps) if an input file  shrinks  while
      grep is operating, or if an I/O error occurs.

mmapの詳細については、 this または this を参照してください。

1
Ramzi Kahil