zstd(Zstandard)は、Meta(旧 Facebook)の Yann Collet 氏が開発した可逆圧縮ツールです。gzip と同等以上の圧縮率を保ちながら、解凍が圧倒的に速いのが最大の特徴で、RFC 8878 として標準化されています。
この記事では基本的な使い方に加えて、実際に 73MiB のアクセスログを gzip / xz / bzip2 と圧縮し比べた実測値と、公式ドキュメントに書かれていない「ハマりどころ」を、すべて手元の Ubuntu 24.04 + zstd 1.5.5 で検証した結果として掲載します。
構文(Syntax)
zstd [オプション] ファイル名 # 圧縮(file → file.zst)
zstd -d [オプション] ファイル名.zst # 解凍(file.zst → file)
unzstd ファイル名.zst # 解凍(zstd -d と同じ)
zstdcat ファイル名.zst # 解凍せず標準出力に表示
「zstd: command not found」と表示されるときのインストール方法
最近のディストリビューションでは標準で入っていることが多いですが、入っていない場合は以下でインストールします。
Debian / Ubuntu 系
sudo apt update
sudo apt install -y zstd
RHEL / CentOS 系
sudo yum install -y zstd
Fedora / RHEL 8 以降
sudo dnf install -y zstd
インストールできたかは zstd --version で確認します。
$ zstd --version
*** Zstandard CLI (64-bit) v1.5.5, by Yann Collet ***
Ubuntu / Debian の zstd パッケージには、マルチスレッド版の pzstd、解凍用の unzstd、閲覧用の zstdcat、検索用の zstdgrep も同梱されます。
zstd コマンドの主なオプション
| オプション | 説明 | 使用例 |
|---|---|---|
-d | 解凍する | zstd -d access.log.zst |
-1〜-19 | 圧縮レベル(既定は -3) | zstd -10 access.log |
--ultra -20〜-22 | 超高圧縮モード(--ultra が必須) | zstd --ultra -22 access.log |
-T N | スレッド数を指定(-T0 で全コア) | zstd -19 -T0 access.log |
-k | 元ファイルを残す(既定でオン) | zstd -k access.log |
--rm | 圧縮成功後に元ファイルを削除 | zstd --rm access.log |
-o FILE | 出力先ファイル名を指定 | zstd access.log -o backup.zst |
-c | 標準出力へ書き出す(パイプ用) | zstd -c access.log > a.zst |
-f | 確認なしで上書き | zstd -f access.log |
-t | 圧縮ファイルの整合性を検証 | zstd -t backup.tar.zst |
-l | 中身の情報を表示(解凍しない) | zstd -l backup.tar.zst |
--adapt | I/O 速度に応じてレベルを自動調整 | zstd --adapt -T0 -c big.log > a.zst |
-q | 進捗表示を抑制(cron 向け) | zstd -q access.log |
実行例(圧縮)
ファイルを圧縮する
zstd access.log
access.log.zst が作られます。gzip と違い、元の access.log はそのまま残ります。この違いは後述の「つまずきポイント」で詳しく説明します。
圧縮レベルを指定する
zstd -10 access.log # 既定(-3)より高圧縮
zstd -19 -T0 access.log # 最高圧縮+全コア使用
zstd --ultra -22 access.log # 20以上は --ultra が必要
圧縮後に元ファイルを削除する
zstd --rm access.log
出力先ファイル名を指定する
zstd access.log -o /backup/access-20260815.zst
パイプで受け取って圧縮する
mysqldump -u root -p mydb | zstd -19 -T0 > mydb.sql.zst
ダンプを一時ファイルに落とさず直接圧縮できるため、ディスクの空きが少ないサーバーで有効です。詳しくは mysqldump コマンドの記事も参考にしてください。
実行例(解凍)
解凍する
zstd -d access.log.zst
# または
unzstd access.log.zst
実行すると、拡張子 .zst を取り除いた access.log が復元されます。
$ zstd -d small.log.zst
small.log.zst : 200000 bytes
解凍せずに中身を見る
zstdcat access.log.zst | less
zstdcat access.log.zst | tail -100
zstdgrep ' 500 ' access.log.zst # 圧縮したまま grep できる
圧縮したログをディスクに展開せず調査できるので、容量が逼迫しているサーバーで重宝します。
中身の情報を確認する
$ zstd -l small.log.zst
Frames Skips Compressed Uncompressed Ratio Check Filename
1 0 18.7 KiB 195 KiB 10.457 XXH64 small.log.zst
壊れていないか検証する
$ zstd -t backup.tar.zst
backup.tar.zst : 77199360 bytes
$ echo $?
0
zstd は XXH64 チェックサムを内蔵しているため、破損を確実に検出できます。実際に圧縮ファイルの途中 4 バイトを書き換えて試すと、次のように終了ステータス 1 で失敗します。
$ zstd -t broken.zst
broken.zst : Decoding error (36) : Data corruption detected
$ echo $?
1
終了ステータスで判定できるので、バックアップスクリプトに検証ステップを組み込めます。
if zstd -q -t backup.tar.zst; then
echo "バックアップは正常です"
else
echo "バックアップが破損しています" >&2
exit 1
fi
実測:gzip / xz / bzip2 と比べてどれくらい速いのか
「zstd は速い」とよく言われますが、実際の差を確かめるため、Nginx 形式のアクセスログ 73.42MiB(40 万行)を各ツールで圧縮・解凍して計測しました。
検証環境: Ubuntu 24.04.4 LTS / 6 コア / zstd 1.5.5 / gzip・xz・bzip2 はディストリ標準版。時間は /usr/bin/time による実時間、いずれも 1 スレッド(-T0 なし)での測定です。
| コマンド | 圧縮時間 | 解凍時間 | 圧縮後サイズ | 圧縮率 |
|---|---|---|---|---|
zstd -1 | 0.13 秒 | 0.05 秒 | 6.44 MiB | 11.4 倍 |
zstd -3(既定) | 0.17 秒 | 0.05 秒 | 6.29 MiB | 11.7 倍 |
gzip -6(既定) | 0.87 秒 | 0.26 秒 | 6.09 MiB | 12.1 倍 |
gzip -9 | 1.66 秒 | 0.26 秒 | 5.76 MiB | 12.7 倍 |
zstd -10 | 1.56 秒 | 0.04 秒 | 5.00 MiB | 14.7 倍 |
bzip2 -9 | 13.94 秒 | 1.57 秒 | 3.28 MiB | 22.4 倍 |
xz -6 | 18.82 秒 | 0.25 秒 | 4.45 MiB | 16.5 倍 |
zstd -19 | 55.94 秒 | 0.05 秒 | 4.33 MiB | 17.0 倍 |
この結果から読み取れることを整理します。
- 解凍速度は zstd が圧倒的。レベルに関係なく約 0.05 秒で、
gzipの 0.26 秒に対して約 5 倍速く、bzip2の 1.57 秒に対しては約 30 倍速い結果でした。「1 回圧縮して何度も読む」ログやバックアップでは、この差がそのまま作業時間の差になります。 zstd -10はgzip -9の上位互換に近い。圧縮時間はほぼ同じ(1.56 秒 対 1.66 秒)で、サイズは 5.00MiB 対 5.76MiB と zstd の方が小さく、解凍は 6 倍以上速いという結果です。gzip -9を使っている場面はzstd -10に置き換えて損がありません。- 既定値どうし(
zstd -3対gzip -6)ならサイズはほぼ互角で、速度だけが 5 倍違う。サイズは 6.29MiB 対 6.09MiB とわずかに gzip 有利ですが、圧縮時間は 0.17 秒 対 0.87 秒です。 zstd -19はxz -6より小さく、解凍は 5 倍速い。ただし圧縮に 55.94 秒かかりxz -6の 3 倍です。後述の-T0を付けると 25.89 秒まで縮みます。- 圧縮率だけを見れば bzip2 が最も小さい。今回のような繰り返しの多い構造化テキストでは
bzip2のアルゴリズム(BWT)が有利に働きます。zstd は「最小サイズ」ではなく「速度と圧縮率のバランス」で選ぶツールだと理解しておくと判断を誤りません。
なお、圧縮率はデータの性質で大きく変わります。上の数値はログのような繰り返しの多いテキストでの結果であり、JPEG や MP4 のような圧縮済みファイルではどのツールもほとんど縮みません。手元のデータで判断したい場合は zstd -b(内蔵ベンチマーク)が使えます。
zstd -b1 -e19 access.log # レベル1〜19を自動で計測
-T0 で全コアを使う(マルチスレッド圧縮)
zstd は圧縮のマルチスレッド化に対応しており、-T0 を付けるだけで利用可能な全コアを使います。同じ 73.42MiB のログを 6 コアで計測した結果が以下です。
| コマンド | 圧縮時間 | 圧縮後サイズ |
|---|---|---|
zstd -10 | 1.57 秒 | 5,246,512 バイト |
zstd -10 -T0 | 0.69 秒(2.3 倍速) | 5,246,512 バイト(同一) |
zstd -19 | 55.84 秒 | 4,538,157 バイト |
zstd -19 -T0 | 25.89 秒(2.2 倍速) | 4,538,157 バイト(同一) |
注目したいのは圧縮後サイズが 1 バイトも変わっていない点です。-T0 は圧縮結果を犠牲にせず時間だけを短縮するため、バッチ処理では基本的に付けておいて構いません。
ただし本番サーバーで全コアを占有すると他のプロセスに影響します。コア数を明示して加減するのが安全です。
zstd -19 -T2 access.log # 2スレッドだけ使う
nice -n 19 zstd -19 -T0 access.log # 優先度を下げて全コア使う
解凍はマルチスレッド化されないため、-T0 を付けても解凍は速くなりません(元々十分速いため実用上の問題はありません)。
tar と組み合わせて .tar.zst を作る
zstd 単体では複数ファイルをまとめられないため、ディレクトリを圧縮するときは tar と組み合わせます。
圧縮する(GNU tar 1.31 以降)
tar --zstd -cf backup.tar.zst /var/www/html/
展開する
tar --zstd -xf backup.tar.zst
tar --zstd -tf backup.tar.zst # 展開せず中身の一覧を見る
圧縮レベルやスレッド数を指定する
--zstd は既定レベル(-3)で動くため、レベルや -T0 を効かせたい場合は -I で圧縮コマンドごと渡します。
tar -I 'zstd -19 -T0' -cf backup.tar.zst /var/www/html/
実際に同じディレクトリで比べると、--zstd では 6,615,380 バイト、-I 'zstd -19 -T0' では 4,552,222 バイトと、約 31% 小さくなりました。クォートで囲むことを忘れないでください。囲まないと -19 が tar のオプションとして解釈されます。
古い tar で .tar.zst を展開する
GNU tar 1.30 以前や macOS 標準の BSD tar では --zstd が使えません。その場合はパイプでつなぎます。
zstd -dc backup.tar.zst | tar -xf -
圧縮する場合も同様です。
tar -cf - /var/www/html/ | zstd -19 -T0 > backup.tar.zst
tar のバージョンは tar --version で確認できます。
実務レシピ:logrotate で zstd 圧縮する
logrotate は既定で gzip を使いますが、compresscmd を差し替えると zstd を使えます。以下は実際に動作確認した設定です。
/var/log/myapp/app.log {
daily
rotate 4
missingok
compress
compresscmd /usr/bin/zstd
compressoptions -19 -T0
compressext .zst
uncompresscmd /usr/bin/unzstd
}
設定を書いたら、-d(デバッグ、実際には変更しない)で確認してから -f で強制実行してテストします。
logrotate -d /etc/logrotate.d/myapp # 動作確認のみ
logrotate -f /etc/logrotate.d/myapp # 強制実行
logrotate 3.21.0 で検証したところ、約 2.9MiB のログが app.log.1.zst として 183KiB まで圧縮されました。--rm を書かなくても、ローテート元のファイルは logrotate 自身が削除します。
注意:compressoptions の値をクォートで囲んではいけません。次のように書くと失敗します。
# NG: クォートすると1つの引数として渡されてしまう
compressoptions "-19 -T0"
error: Compressing program wrote following message to stderr when compressing log
/var/log/myapp/app.log.1:
Incorrect parameters
error: failed to compress log /var/log/myapp/app.log.1
Incorrect parameters というメッセージだけでは原因がわかりにくいですが、クォートを外せば解決します。ログ運用全体の設計は logrotate の記事と 定期バックアップの記事もあわせて確認してください。
つまずきポイントと対処
1. gzip と違い、元ファイルが消えない
もっとも間違えやすい違いです。同じファイルを両方で圧縮すると挙動がはっきり分かれます。
$ cp access.log a.log; cp access.log b.log
$ gzip a.log # gzip は元ファイルを削除する
$ zstd -q b.log # zstd は元ファイルを残す
$ ls a.log a.log.gz b.log b.log.zst
ls: cannot access 'a.log': No such file or directory
a.log.gz
b.log
b.log.zst
gzip のつもりでバッチを組むと、ディスクを空けるために圧縮したのに元ファイルが残って容量が減らないという事故になります。削除したい場合は明示的に --rm を付けてください。
zstd --rm access.log
2. -22 を指定しても、–ultra がないと黙ってレベル19になる
レベル 20 以上には --ultra が必要ですが、付け忘れてもエラーにはならず、警告を出してレベル 19 に下げられます。終了ステータスも 0 です。
$ zstd -22 -c access.log > out.zst
Warning : compression level higher than max, reduced to 19
$ echo $?
0
実際に出力を比べると、-22(--ultra なし)と -19 はバイト単位で完全に一致しました。
-22(--ultraなし): 4,538,157 バイト
-19 : 4,538,157 バイト ← 完全一致
--ultra -22 : 4,392,987 バイト ← こちらが本来のレベル22
スクリプトでは警告が -q や 2>/dev/null で消えてしまうため、最高圧縮のつもりが実は 19 だったと気づきにくい点に注意してください。レベル 20 以上を使うときは必ず --ultra をセットで書きます。
3. cron で実行すると「already exists」で止まる
出力先がすでに存在すると、zstd は上書き確認を求めます。端末がない cron では確認できず、終了ステータス 1 で失敗します。
$ zstd access.log -o backup.zst
zstd: backup.zst already exists; overwrite (y/n) ? Not overwritten
$ echo $?
1
定期実行するスクリプトでは -f(強制上書き)と -q(進捗抑制)を付けておくのが安全です。
zstd -q -f -19 -T0 access.log -o /backup/access.zst
4. zstd -l で元のサイズが空欄になる
パイプ経由で作った .zst は、圧縮時に元サイズが確定していないためヘッダーに記録されません。その結果 zstd -l の Uncompressed 欄と Ratio 欄が空になります。tar --zstd で作った書庫も同様です。
$ cat small.log | zstd -q > pipe.log.zst
$ zstd -l pipe.log.zst
Frames Skips Compressed Uncompressed Ratio Check Filename
1 0 18.2 KiB XXH64 pipe.log.zst
元サイズを記録したい場合は --stream-size であらかじめ渡します。
$ cat small.log | zstd -q --stream-size=$(stat -c%s small.log) > pipe2.log.zst
$ zstd -l pipe2.log.zst
Frames Skips Compressed Uncompressed Ratio Check Filename
1 0 18.7 KiB 195 KiB 10.457 XXH64 pipe2.log.zst
なお、サイズが空欄でもデータそのものは正常です。zstd -t での検証や解凍には影響しません。
5. –long を付けても必ず縮むわけではない
遠く離れた重複を検出する --long は、巨大な VM イメージなどで効果がありますが、今回のアクセスログでは逆にわずかに増えました。
zstd -10 -T0 : 5,246,512 バイト
zstd -10 -T0 --long=27 : 5,291,995 バイト ← むしろ増えた
--long は解凍時にも同じだけのメモリ(--long=27 で約 128MB)を要求します。効果を実測してから採用してください。
.gz / .zst / .xz / .zip の違い
| 形式 | コマンド | 特徴 | 複数ファイル | 主な用途 |
|---|---|---|---|---|
.zst | zstd / unzstd | 解凍が非常に速い。速度と圧縮率のバランス型 | ✗(tar と併用) | ログ圧縮、バックアップ、配布物 |
.gz | gzip / gunzip | どこでも動く事実上の標準。互換性は最高 | ✗(tar と併用) | ログ圧縮、パイプ処理 |
.xz | xz / unxz | 高圧縮だが圧縮が遅い | ✗(tar と併用) | ソース配布、長期保管 |
.zip | zip / unzip | 複数ファイルを 1 つにまとめられる | ✓ | Windows 連携、ファイル配布 |
使い分けの目安は次のとおりです。
- 自分のサーバー内で完結するログ圧縮・バックアップ →
zstd - 相手の環境が不明なファイル受け渡し →
gzip(.tar.gz) - Windows ユーザーとやりとりする →
zip
zstd は比較的新しい形式のため、古い環境ではコマンドが入っていないことがあります。社外に配布するファイルは .tar.gz にしておくほうが安全です。
よくある質問(FAQ)
Q. 圧縮レベルはいくつにすればよいですか?
用途で決めます。リアルタイム処理やパイプ中継なら既定の -3、日次のログ圧縮なら -10 -T0(今回の計測で 0.69 秒・5.00MiB)、月次アーカイブなど時間をかけてよい場面なら -19 -T0 が目安です。-19 は -10 の 37 倍の時間がかかって 13% しか縮まないため、常用は勧めません。
Q. gzip から zstd に乗り換えて大丈夫ですか?
自分が管理するサーバー内で圧縮・解凍が完結するなら問題ありません。ただし .zst を扱えない古い環境や、外部にファイルを渡す場面では gzip のほうが確実です。既存の .gz ファイルはそのまま読めるので、新しく作るものから順に切り替えるのが安全です。
Q. pzstd と zstd -T0 はどちらを使うべきですか?
pzstd は zstd 本体がマルチスレッドに対応する前に作られた別実装です。現在は zstd -T0 で同等のことができるため、新しく書くスクリプトでは zstd -T0 を使ってください。
Q. 圧縮したまま中身を検索できますか?
できます。zstdgrep を使えば解凍せずに grep できます。ディスクの空きがないサーバーでの調査に有効です。
zstdgrep 'error' app.log.zst
zstdgrep -c ' 500 ' access.log.zst # 該当行数を数える
Q. 解凍したデータが元と同じか確認できますか?
md5sum で突き合わせれば確認できます。実際に 73.42MiB のログをパイプ経由で圧縮・解凍したところ、ハッシュは一致しました。
$ md5sum access.log | cut -d' ' -f1
7824f7eaf48dfd18208cd16d332da8a7
$ cat access.log | zstd -q -T0 -19 > dump.zst
$ zstdcat dump.zst | md5sum | cut -d' ' -f1
7824f7eaf48dfd18208cd16d332da8a7
関連コマンド
gzip: 単一ファイルを.gz形式で圧縮・解凍tar: 複数ファイルをまとめてアーカイブ化・圧縮zip/unzip: ZIP 形式の圧縮・解凍logrotate: ログを自動でローテート・圧縮・削除mysqldump: MySQL / MariaDB の論理バックアップ- 定期バックアップ講座 : rsync × 世代管理 × 復元テスト
- linux コマンド一覧 : 用途別に整理した初心者向け完全ガイド
備考
- 本記事の計測値は Ubuntu 24.04.4 LTS / 6 コア / zstd 1.5.5 での実測です。圧縮率・所要時間はデータの性質と CPU 性能で大きく変わるため、目安として参照してください。
- JPEG・MP4・すでに圧縮済みの書庫はほとんど縮みません。効果が高いのはテキスト・ログ・ソースコード・データベースダンプです。
- 圧縮レベルを上げても解凍速度はほぼ変わりません。高いレベルのコストは圧縮時間とメモリにだけ現れます。
参考
- 公式サイト: Zstandard – Real-time data compression algorithm
- ソースコード: github.com/facebook/zstd
- manページ: man7.org zstd(1)

コメント