iostatとiotop:Linuxストレージのボトルネックを診断する
14分で読めます - 2026年6月12日

iostat と iotop を使って、Linux のディスク I/O のボトルネックを見つける。この記事では、NVMe における %util の不具合、読み込み待ちとキューの深さ、そしてそれを発見し修正するためのワークフローについて説明します。
iostat と iotop:Linux ストレージのボトルネック診断
Linuxサーバーの動作が遅いと感じた場合、最初に確認すべき箇所の一つがストレージです。iostatはディスクが過負荷状態にあるかどうかを示し、iotopはどのプロセスが負荷の原因となっているかを示します。これらを併用することで、重要な2つの疑問、「ディスクが実際にボトルネックになっているのか」、そして「もしそうなら、何がディスクに負荷をかけているのか」という疑問に答えられます。 本記事では、インストール方法、出力の読み方(iostatの %util メトリクスの位置を含む)、そして症状から解決策へと至るワークフローについて解説します。
iostat と iotop のインストール
iostatはsysstatパッケージに含まれていますが、iotopは別途提供されています。両方をインストールしてください:
# Debian/Ubuntu
sudo apt install sysstat iotop
# RHEL, AlmaLinux, Rocky, CentOS Stream
sudo dnf install sysstat iotop
# Arch
sudo pacman -S sysstat iotopUbuntu では、sysstat はデフォルトで無効になっています。後で sar、 /etc/default/sysstat、 ENABLED="true"を設定し、サービスを再起動します:
sudo systemctl restart sysstatiotopはroot権限で実行する必要があります。RHEL 9以降では、遅延アカウンティングがデフォルトで無効になっているため、 IO および SWAPIN 列が空になります。次のコマンドで有効にします:
echo 1 | sudo tee /proc/sys/kernel/task_delayacctAdd kernel.task_delayacct = 1 を /etc/sysctl.conf に追加すると、再起動後も設定が維持されます。
iostatの出力を読み取る
iostatを拡張統計モードで実行し、起動以降の平均値のみを表示する最初のサンプルは無視してください:
iostat -xz 2 -x オプションは拡張統計情報を追加し、 -z アイドル状態のデバイスを非表示にし、 2 2秒ごとに更新されます。重要な列は以下の通りです:
await: I/Oリクエストが完了するまでの平均時間(ミリ秒単位)。キュー待ち時間を含む。ユーザーが動作の遅さを訴える際、最も重要な数値である。r/sおよびw/s: 読み取りおよび書き込みのIOPS。rkB/sこれらをwkB/sこれらを組み合わせることで、ワークロードがランダム(高IOPS、低スループット)か、シーケンシャル(低IOPS、高スループット)かを判断できます。aqu-sz: 平均キュー深度。HDDの場合、1を上回る状態が持続すると、ディスクが処理に追いついていないことを意味します。%util: デバイスに少なくとも1つの処理中のI/Oが存在していた時間の割合。HDDでは有用ですが、NVMeでは誤解を招く恐れがあります(後述)。
簡単な閾値の目安:
| ドライブの種類 | 懸念事項 | aqu-szの懸念 | %utilは信頼できるか? |
|---|---|---|---|
| 7200 RPM HDD | > 20 ms | > 1 | はい |
| SATA SSD | > 10 ms | > 4 | 主に |
| NVMe | > 1~2 ms | > 16 | いいえ |
%utilがどこにあるか
%util という指標は、多くの人が真っ先に頼るものですが、NVMeにおいては明らかに誤解を招くものです。カーネルは %util 「その瞬間に進行中のあらゆるI/O」としてカウントします。これは一度に1つのリクエストを処理する回転ディスクにとっては問題ありませんが、ハードウェアキューを介して数千のリクエストを並列に処理するNVMeデバイスにとっては無意味です。NVMeドライブは、実際の容量の5%しか使用していない状態でも %util 状態であっても、実際の容量の5%しか使用していない場合があります。
NVMeでは、 r_await, w_await、 aqu-sz を信頼してください。もし r_await が1ミリ秒未満で、かつキューの深さがデバイスのハードウェアキュー深度(多くの場合1024以上)を十分に下回っている場合、 %util 表示されていても、ドライブは実際には飽和状態ではありません。
kB/s ではなく MB/s 単位で高速 NVMe の状況を確認するには:
iostat -xm 1長期的な収集を行う場合は、後でアプリケーションログと照合できます:
iostat -x -t 5 720 > /var/log/iostat.logこれは1時間にわたり5秒ごとにサンプリングを行います。 sar 同じ sysstat パッケージから取得したデータは、永続的な履歴ストレージを備えた同等のデータを提供し、継続的な監視にはより適しています。
CPUのiowaitとの照合
iostatでストレージへの負荷が確認された場合は、 %iowait 同じ出力の先頭にある CPU サマリーの %iowait 15~20% 以上が持続し、かつ await が組み合わさって15~20% 以上で持続している場合、ボトルネックがストレージであることを裏付けます。もし %iowait が高いが await が正常に見える場合は、 vmstat 1 を実行し、 si および so の列を確認してください。スワップアクティビティがゼロでない場合、メモリがボトルネックとなっており、ディスクトラフィックはアプリケーションのI/Oではなくページングによるものです。
iotopの出力を読み解く
iostatでストレージのボトルネックが確認されたら、iotopを使用して原因となっているプロセスを特定します。以下のコマンドから開始してください:
sudo iotop -o- -o フラグはアイドル状態のプロセスを非表示にし、アクティブにI/Oを行っているプロセスのみを表示します。注目すべき列:
- DISK READ / DISK WRITE: プロセスごとのリアルタイムスループット。明らかな負荷の大きいプロセスを特定します。
- IO: プロセスがI/Oでブロックされている時間の割合。わずか50 kB/sの書き込みを行っているプロセスでも、微小な同期
fsync()呼び出しを行っている場合、わずか50 kB/sの書き込みを行っているプロセスでも99%のIOを示すことがあります。この列は、単純なスループットよりも重要です。 - SWAPIN:スワップページを待機している時間の割合。ここがゼロ以外の場合、システムはページングを行っており、あなたの「ストレージの問題」は実際にはメモリの問題であることを意味します。
マルチスレッドアプリケーション(MySQL、PostgreSQL、Javaワークロード)の場合、スレッドをプロセスに集約し -P、さらに -a を使用して、iotopの起動以来の合計値を算出します:
sudo iotop -oPa`-c` -a フラグは、一度に数秒しか実行されず、ライブビューでは見つけにくいバックアップジョブのようなバースト型のワークロードを捕捉するための秘訣です。
誰も監視していない夜間時間帯の無人ログ記録には:
sudo iotop -botqq -d 10 > /var/log/iotop.logこれにより、10秒ごとに非対話型のスナップショットが書き込まれます。バックアップやcronジョブのタイムスタンプと照合することで、事後的に原因を特定できます。
診断ワークフロー
ディスク I/O の調査の多くは、以下の手順に従います:
iostat -xz 2ディスクが実際にボトルネックであるかを確認します。await,aqu-sz、および%iowaitを確認します。これらが正常であれば、問題はストレージではなく、全く別の場所を探すべきです。iotop -oPa負荷の原因となっているプロセスを特定します。スループットの列よりも、IOの列に注目してください。最も負荷が高いのは、多くの小さな同期書き込みを行うプログラムであることが多く、最も多くのバイトを移動させるプログラムではありません。lsof -p <pid>そのプロセスがどのファイルを操作しているかを確認します。これにより、通常はワークロードの種類が即座に特定されます。データベースの書き込み先行ログ、アプリケーションのログファイル、バックアップのマウントポイント、一時ファイルなどです。
知っておくべき2つのパターン。
次のようなカーネルスレッドが見られる場合 jbd2/... (ext4 ジャーナル) や txg_sync (ZFS) のようなカーネルスレッドが iotop のライターの上位に表示されている場合、それらは書き込みを開始しているのではなく、他のプロセスからの書き込みに応答しているだけです。ジャーナルトラフィックを引き起こしているユーザー空間のプロセスが実際の原因です。さらに調査を続けてください。
VPS において、 await で %util という組み合わせは、典型的な「ノイジー・ネイバー」現象の兆候です。別のテナントが共有ストレージを独占しており、I/Oは仮想ディスク側ではなくハイパーバイザー側でキューに溜まっている状態です。ゲスト環境内からはこれを確認することはできても修正はできません。解決策としては、プロバイダーにエスカレーションするか、ストレージが分離されたサーバーに移行するかのいずれかです。
一般的なI/Oボトルネックの解消
ディスクへの負荷の原因が分かれば、その解決策は通常、単純明快です。
重要度の低い I/O の優先度を下げます。 ionice これにより、プロセスはアイドルスケジューリングクラスに配置され、他のプロセスがディスク帯域幅を必要としていない場合にのみ使用します:
ionice -c 3 -p <pid>
sudo ionice -c 3 rsync -a /data /backup最初の形式は実行中のプロセスを変更し、2番目の形式は最初からアイドルクラスに属する新しいプロセスを起動します。iotop内では、iキーを押すことで実行中のプロセスの優先度を対話的に変更できます。
負荷の高いワークロードをより高速なストレージに移す。iostatでデータベースの書き込みによりSATAディスクが過負荷になっていることが確認され、同じマシン内に未使用のNVMeがある場合は、データベースのデータディレクトリを移動させる。IOPSにおける桁違いの差により、これは最も効果の高い解決策となる。
適切なI/Oスケジューラを設定します。最近のカーネルではデフォルト設定が適切ですが、確認する価値はあります。NVMeやSSDの場合は、スケジューラを noneに設定します。デバイス側では、カーネルよりもハードウェアレベルでキューイングを効率的に処理できるためです:
echo none > /sys/block/nvme0n1/queue/scheduler混合ワークロードを処理するHDDの場合、 mq-deadline が一般的な選択です。
noatimeオプションでマウントする。デフォルトでは、読み取り操作のたびにファイルの最終アクセス時刻が更新され、読み取りごとに書き込みが発生する。読み取りが中心のファイルシステムでは、これは無駄なI/Oとなる。マウントオプションに noatime をマウントオプションに追加します /etc/fstab:
UUID=... /data ext4 defaults,noatime 0 2バースト的な書き込みに対しては、writebackを調整してください。RAMが十分に確保されたサーバーでは、デフォルトのダーティページ閾値により、ページキャッシュにギガバイト単位の未書き込みデータが蓄積され、その後一度に大量のフラッシュが行われることがあります。これを緩和するには、 /etc/sysctl.conf この現象を緩和するためにしきい値を下げてください:
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5通常、ディスク自体が問題となることは稀です。iostatで高いIOPSと低いスループットが確認される場合、ワークロードがシーケンシャル処理可能なデータに対してランダムI/Oを行っていたり、バッチ処理可能な多数の小さな書き込みを実行していたりする可能性があります。ハードウェアのせいにする前に、アプリケーションを確認してください。
ネットワークがディスクの処理速度を上回るサーバーでストレージ負荷の高いワークロードを実行している場合、FDCのNVMe搭載専用サーバーなら、上記のチューニングを効果的に適用するための余裕が得られます。

Linuxサーバーのワークロード最適化のためのチューニング・プロファイル
GPU、データベース、高帯域幅 Linux サーバー用の調整済みプロファイルの選択、適用、カスタマイズ方法について、例と Ansible 導入のヒントを示します。
16分で読めます - 2026年6月9日
Linux OOM Killer Tuning for VPS: 実践ガイド
12分で読めます - 2026年6月8日

ご質問またはカスタムソリューションが必要ですか?
柔軟なオプション
グローバル・リーチ
即時展開
柔軟なオプション
グローバル・リーチ
即時展開