背景:
grepコマンドを使ってデータ補正処理を行う際、大量データの場合、時間がかかります。
本番環境では、数時間の余裕はなかなか厳しいですね。
なので、今回はgrepコマンドの性能について、調べました。
調査結果
grepコマンドは1行ずつの実行と一括実行の違いがあります。
各自の処理時間を一覧化しました。
grep 1行ずつ実行 (ループで)と一括実行 (-fオプションを使う)
処理 | grep 1行ずつ実行 | grep一括実行 |
---|---|---|
コマンド⇒ patten.txt :14桁/1行 input.txt:34桁/1行 |
cat patten.txt | while read line do grep ${line} input.txt >> output.txt done |
grep -f patten.txt input.txt > output.txt |
テスト条件: patten.txt:1万行 input.txt :10万行 |
処理時間:37秒 | 処理時間:2秒 |
patten.txt:5万行 input.txt :10万行 |
処理時間:3分7秒 | 処理時間:1分14秒 |
patten.txt:10万行 input.txt :10万行 |
処理時間:6分30秒 | 強制終了で処理不能 |
分析:
上記の一覧表から見ると、大量データの場合、一括実行(grep -f)の性能が良いですが、
データ量の増加に従い、性能が悪くなる傾向があります。
また、ある程度の量(今回実証実験が10万件)を超えると、強制終了で処理不能となります。
1行ずつの実行がエラーにならないが、性能が喜ばないです。
対策案
1行ずつの実行か、一括実行か、どちら選ぶか?
性能が良いし、エラーにならない対策がありますか。
下記の提案を致します。
①一括実行(grep -f)を優先します。
②1000件超えると強制終了が出るかを確認
③大量データかつ性能重視の場合、patten.txtを分割して一括実行
補足(分割一括実行案)
patten.txtを分割して一括実行の例
#!/bin/sh
#patten.txtを10000行ずつ分割、分割したファイルはpatten_splitaa,patten_splitab...になる
split -l 10000 patten.txt patten_split
ptn_list=`ls patten_split*`
for f in ${ptn_list}
do
grep -f ${f} input.txt >> output.txt
done
このやり方で、1万行の処理が2秒の場合、5万件なら10秒、10万件なら20秒。
性能が悪くなる傾向がありません。
コメント欄