これが私の問題です。大きなgz
ログファイルのセットがあり、行の最初の情報は日時テキストです(例:2014-03-20 05:32:00)。
特定のデータを保持しているログファイルのセットを確認する必要があります。 initの場合は、次のようにします。
'-query-data-'
zgrep -m 1 '^20140320-04' 20140320-0{3,4}*gz
しかし、zcatで行うのと同じように、ファイル全体を処理せずに最後の行で同じことを行うには(重い):
zcat foo.gz | tail -1
追加情報、これらのログは最初のレコードのデータ時間で作成されるため、14:00:00でログをクエリしたい場合は、14:00:00より前に作成されたファイルもファイルと同様に検索する必要があります。 13:50:00に作成され、14:10:00に閉じられます。
最も簡単な解決策は、ログローテーションを変更して小さなファイルを作成することです。
2番目に簡単な解決策は、ランダムアクセスをサポートする圧縮ツールを使用することです。
dictzip 、 [〜#〜] bgzf [〜#〜] 、および csio のようなプロジェクトは、それぞれ追加 sync flush points = gzip圧縮されたデータ内のさまざまな間隔で、その追加情報を認識しているプログラムでシークできるようにします。標準には存在しますが、Vanilla gzip
はデフォルトでもオプションでもこのようなマーカーを追加しません。
これらのランダムアクセス対応のユーティリティで圧縮されたファイルは、マーカー自体のために少し大きい(おそらく2〜20%)が、これらのマーカーを認識しないgzip
または別のユーティリティでの解凍を完全にサポートします。
さまざまな圧縮形式でのランダムアクセス に関するこの質問で詳細を学ぶことができます。
このトピックに関するいくつかの投稿を含む、Peter Cockによる「Blasted Bioinformatics」ブログもあります。
xz
の実験xz
( [〜#〜] lzma [〜#〜] 圧縮形式)は実際にはブロックごとのレベルでランダムアクセスをサポートしていますが、デフォルトの単一ブロックのみを取得します。
xz
は複数のアーカイブを連結できます。その場合、各アーカイブには独自のブロックがあります。 GNU split
はこれを簡単に行うことができます:
split -b 50M --filter 'xz -c' big.log > big.log.sp.xz
これはsplit
にbig.log
を50MBのチャンク(before圧縮)に分割し、圧縮されたチャンクを標準に出力するxz -c
を通じてそれぞれを実行するように指示します出力。次に、その標準出力をbig.log.sp.xz
という名前の単一のファイルに収集します。
GNUなしでこれを行うには、ループが必要です。
split -b 50M big.log big.log-part
for p in big.log-part*; do xz -c $p; done > big.log.sp.xz
rm big.log-part*
xz --verbose --list FILE.xz
を使用してブロックオフセットのリストを取得できます。最後のブロックが必要な場合は、その圧縮サイズ(列5)+オーバーヘッド用の36バイトが必要です(サイズをhd big.log.sp0.xz |grep 7zXZ
と比較するとわかります)。 tail -c
を使用してそのブロックをフェッチし、xz
を介してパイプします。上記の質問ではファイルの最後の行が必要なので、tail -n1
を介してパイプします。
SIZE=$(xz --verbose --list big.log.sp.xz |awk 'END { print $5 + 36 }')
tail -c $SIZE big.log.sp.xz |unxz -c |tail -n1
バージョン5.1.1では、--block-size
フラグのサポートが導入されました。
xz --block-size=50M big.log
ただし、ブロック間の完全なヘッダーが含まれていないため、特定のブロックを抽出できませんでした。これはコマンドラインから行うのは簡単なことではないかと思います。
gzip
の実験gzip
は連結もサポートしています。私は(簡単に)gzip
に対してこのプロセスを模倣しようとしましたが、運がありませんでした。 gzip --verbose --list
は十分な情報を提供しておらず、ヘッダーが可変であることがわかりません。
これには同期フラッシュポイントを追加する必要があり、それらのサイズは前回の圧縮の最後のバッファーのサイズによって異なるため、コマンドラインで実行するのは困難です(dictzipまたは前述の別のツールを使用します)。
私はapt-get install dictzip
をしてdictzipで遊んでみましたが、ほんの少しです。引数なしでは機能せず、dictunzip
もgunzip
も理解できない(大量の).dz
アーカイブを作成します。
bzip2
の実験bzip2
には、見つけることができるヘッダーがあります。これはまだ少し厄介ですが、動作します。
これは、上記のxz
プロシージャと同じです。
split -b 50M --filter 'bzip2 -c' big.log > big.log.sp.bz2
これはかなりがxz
よりも遅いことに注意してください(bzip2の48分vs xzの17分vs xz -0
の1分)。かなり大きい(bzip2の97M対xz -0
の25M対xzの15M)、少なくとも私のテストログファイルでは。
ニースインデックスがないため、これは少し難しいです。どこに行くべきかを推測する必要があり、スキャンのしやすさを誤る必要がありますが、ファイルが大きい場合でも、I/Oを節約できます。
このテストの私の推測は50000000でした(元の52428800のうち、H.264映画などには十分に悲観的ではない悲観的推測です)。
GUESS=50000000
LAST=$(tail -c$GUESS big.log.sp.bz2 \
|grep -abo 'BZh91AY&SY' |awk -F: 'END { print '$GUESS'-$1 }')
tail -c $LAST big.log.sp.bz2 |bunzip2 -c |tail -n1
これは、最後の5,000万バイトだけを取り、最後のBZIP2ヘッダーのバイナリオフセットを見つけ、それを推測サイズから差し引いて、ファイルの末尾からそのバイト数を引き出します。その部分だけが解凍され、tail
にスローされます。
これは圧縮ファイルを2回クエリする必要があり、追加のスキャン(ヘッダーを探すgrep
呼び出し、推測された領域全体を調べる)があるため、これは最適ではないソリューションです。 bzip2
が実際にどれほど遅いかについては、以下のセクションもご覧ください。
xz
がどれほど高速であるかを考えると、簡単に最善の策です。最も高速なオプション(xz -0
)を使用すると、圧縮または解凍が非常に高速になり、テストしたログファイルにgzip
またはbzip2
よりも小さいファイルが作成されます。他のテスト(およびオンラインのさまざまなソース)は、すべてのシナリオでxz -0
がbzip2
よりも望ましいことを示唆しています。
—————ランダムアクセスなし—————— ———————ランダムアクセス——————— フォーマットサイズ比率書き込み読み取りサイズ比率書き込みシーク ————————— ————————————————————————————————————— ————————————————————— (元の)7211M 1.0000-0:06 7211M 1.0000-0:00 bzip2 96M 0.0133 48 :31 3:15 97M 0.0134 47:39 0:00 gzip 79M 0.0109 0:59 0:22 dictzip 605M 0.0839 1:36(失敗) xz -0 25M 0.0034 1:14 0:12 25M 0.0035 1:08 0:00 xz 14M 0.0019 16:32 0:11 14M 0.0020 16:44 0:00
タイミングテストは包括的ではなく、何も平均化せず、ディスクキャッシュが使用されていました。それでも、それらは正しいように見えます。 split
によるオーバーヘッドはごくわずかで、1つではなく145個の圧縮インスタンスを起動します(これはネットゲインの場合もあります)それ以外の場合はマルチスレッド化されていないユーティリティが複数のスレッドを使用できるようにする場合)。
さて、以前に各ファイルにindexを作成した場合、できますgzip圧縮ファイルにランダムにアクセスできます。 。
gzipファイルのインデックスを作成するコマンドラインツールを開発しました。これにより、ファイル内でのランダムアクセスが非常に高速になります: https:// github.com/circulosmeos/gztool
このツールには、次の2つのオプションがあります。
$ gztool -t foo.gz | tail -1
インデックスが存在しない場合、完全な解凍と同じ時間がかかりますが、インデックスが再利用可能であるため、次回の検索にかかる時間が大幅に短縮されることに注意してください。このツールは 元のzlibのzran.cデモンストレーションコード に基づいているため、ルール外の魔法はありません。