数百万行あるログから、ごく一部分の期間を最短時間で取得
課題
システムを運用していると数百万行を超える膨大なログの中から、ほんの数行のログを抜き出したいことがある。
それもできることなら時間もかけず、サーバーに負荷もかけずに行いたい。
検証
Vagrantで仮想マシンCentOS 6.4を立ち上げて検証。
実現するアプローチはいくつもあるが、今回は大きく2つを調べる。
・sedコマンドで行数を指定して抽出
・headで一度抜き取り、そこからtail
どちらが短時間で目的を達成できるか検証した。
検証対象のファイルは500万行あるログファイルとし、
頭の方( 1万行目~ 1万1000行目)
中の方(250万行目~250万1000行目)
下の方(499万行目~499万1000行目)
の3パターンで検証した。
頭の方( 1万行目~ 1万1000行目)
抽出条件
10,000件目から11,000件目の1000件を抜き出す。
sedコマンドによる抽出
time sed -n 10000,10999p nginx_access.log > sed-output
real 5m1.768s
user 0m0.330s
sys 0m40.347s
sedコマンドでは約5分強かかった。
head->tailによる抽出
time head -n 10999 nginx_access.log | tail -n 1000 > headtail-output
real 0m1.097s
user 0m0.000s
sys 0m0.084s
約1秒で抽出ができた。
差分確認
もちろんsedで取り出しても、head->tailで取り出しても中身は同じ。
diff headtail-output sed-output
(何も表示されない。差分なし)
中の方(250万行目~250万1000行目)
抽出条件
2,500,000件目から2,501,000件目の1000件を抜き出す。
sedコマンドによる抽出
time sed -n 2500000,2500999p nginx_access.log > sed-output
real 4m38.208s
user 0m0.439s
sys 0m41.766s
約4分40秒かかった。
head->tailによる抽出
time head -n 2500999 nginx_access.log | tail -n 1000 > headtail-output
real 4m26.298s
user 0m0.684s
sys 0m32.164s
約4分半かかった。
若干head->tailのが早いが、その差は10秒程度。
vagrantを使って自分のマシンに仮想サーバでの検証なので、ほとんど誤差かもしれない。
差分確認
もちろんsedで取り出しても、head->tailで取り出しても中身は同じ。
diff headtail-output sed-output
(何も表示されない。差分なし)
下の方(499万行目~499万1000行目)
抽出条件
4,990,000件目から4,991,000件目の1000件を抜き出す。
sedコマンドによる抽出
time sed -n 4990000,4990999p nginx_access.log > sed-output
real 5m1.196s
user 0m0.431s
sys 0m42.043s
約5分強かかった。
head->tailによる抽出
time head -n 4990999 nginx_access.log | tail -n 1000 > headtail-output
real 10m57.515s
user 0m1.098s
sys 0m25.951s
下の方だとhead->tailは11分かかった。
sedコマンドでは安定の5分での取得。
逆にtail->head であればすぐに取得が可能だった。
差分確認
もちろんsedで取り出しても、head->tailで取り出しても中身は同じ。
diff headtail-output sed-output
(何も表示されない。差分なし)
結論
簡単にsedコマンドで取得しがちだが、
ファイルの上の方の情報を取得したい場合は head->tailが最も早い。
(逆に下の方の情報を取得したい場合は tail->head)
sedコマンドによる情報取得は早くはないが、抽出場所(上か中か下か)による影響は受けない。