Linux ディスクのシーケンシャル書き込みとランダム書き込みの方法

Linux ディスクのシーケンシャル書き込みとランダム書き込みの方法

1. はじめに

● ランダム書き込みではヘッドがトラックを頻繁に変更するため、効率が大幅に低下します。一方、シーケンシャル書き込みではヘッドがトラックを変更する必要はほとんどないか、変更時間が非常に短くなります。● この記事では、2つの具体的な違いと対応するカーネル呼び出しについて説明します。

2. 環境整備

コンポーネントバージョン
OS Ubuntu 16.04.4 LTS
フィオ2.2.10

3. fioの紹介

fio テストは、読み取りと書き込みの状態を反映できます。fio 出力レポートのいくつかの重要な指標に注目する必要があります。
slat: I/O 送信から実際の I/O 実行までの時間を指します (送信レイテンシ)
clat: I/O 送信から I/O 完了までの時間 (完了待ち時間) を指します。
lat: fio が I/O を作成してから I/O が完了するまでの合計時間を指します。
bw: スループット
iops: 1秒あたりのI/O操作数

4. 同期書き込みテスト

(1)同期ランダム書き込み

fio は主にテストツールとして使用されます。システムコールを確認するには、strace ツールを使用します。コマンドは次のようになります。

まずはランダム書き込みをテストしてみましょう

strace -f -tt -o /tmp/randwrite.log -D fio -name=randwrite -rw=randwrite \
-direct=1 -bs=4k -size=1G -numjobs=1 -group_reporting -filename=/tmp/test.db

重要な情報を抽出する

root@wilson-ubuntu:~# strace -f -tt -o /tmp/randwrite.log -D fio -name=randwrite -rw=randwrite \
> -direct=1 -bs=4k -size=1G -numjobs=1 -group_reporting -filename=/tmp/test.db
randwrite: (g=0): rw=randwrite、bs=4K-4K/4K-4K/4K-4K、ioengine=sync、iodepth=1
fio-2.2.10
1 プロセスを開始
...
randwrite: (グループID=0、ジョブ=1): err= 0: pid=26882: 2019年8月14日水曜日10:39:02
 書き込み: io=1024.0MB、bw=52526KB/s、iops=13131、runt= 19963msec
 clat (usec): 最小=42、最大=18620、平均=56.15、標準偏差=164.79
  緯度 (usec): 最小=42、最大=18620、平均=56.39、標準偏差=164.79
...
 bw (KB /s): 最小=50648、最大=55208、パーセンテージ=99.96%、平均=52506.03、標準偏差=1055.83
...

実行ステータス グループ 0 (すべてのジョブ):
 書き込み: io=1024.0MB、aggrb=52525KB/秒、minb=52525KB/秒、maxb=52525KB/秒、mint=19963ミリ秒、maxt=19963ミリ秒

ディスク統計(読み取り/書き込み):
...
 sda: ios=0/262177、マージ=0/25、ティック=0/7500、in_queue=7476、util=36.05%

注目すべき情報は次のとおりです。

(1)クラット、平均持続時間は約56ミリ秒

(2)緯度、平均持続時間は約56ミリ秒

(3)帯域幅、スループット、約52M

カーネル呼び出し情報を見てみましょう。

root@wilson-ubuntu:~# /tmp/randwrite.log の詳細
...
26882 10:38:41.919904 lseek(3, 665198592, SEEK_SET) = 665198592
26882 10:38:41.919920 書き込み(3, "\220\240@\6\371\341\277>\0\200\36\31\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
26882 10:38:41.919969 lseek(3, 4313088, SEEK_SET) = 4313088
26882 10:38:41.919985 write(3, "\220\240@\6\371\341\277>\0\200\36\31\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
26882 10:38:41.920032 lseek(3, 455880704, SEEK_SET) = 455880704
26882 10:38:41.920048 書き込み(3, "\220\240@\6\371\341\277>\0\200\36\31\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
26882 10:38:41.920096 lseek(3, 338862080, SEEK_SET) = 338862080
26882 10:38:41.920112 write(3, "\220\240@\6\371\341\277>\0\2402\24\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
26882 10:38:41.920161 lseek(3, 739086336, SEEK_SET) = 739086336
26882 10:38:41.920177 書き込み(3, "\220\240@\6\371\341\277>\0\2402\24\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
26882 10:38:41.920229 lseek(3, 848175104, SEEK_SET) = 848175104
26882 10:38:41.920245 write(3, "\220\240@\6\371\341\277>\0\2402\24\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
26882 10:38:41.920296 lseek(3, 1060147200, SEEK_SET) = 1060147200
26882 10:38:41.920312 書き込み(3, "\220\240@\6\371\341\277>\0\2402\24\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
26882 10:38:41.920362 lseek(3, 863690752, SEEK_SET) = 863690752
26882 10:38:41.920377 書き込み(3, "\220\240@\6\371\341\277>\0\2402\24\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
26882 10:38:41.920428 lseek(3, 279457792, SEEK_SET) = 279457792
26882 10:38:41.920444 書き込み(3, "\220\240@\6\371\341\277>\0\2402\24\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
26882 10:38:41.920492 lseek(3, 271794176, SEEK_SET) = 271794176
26882 10:38:41.920508 書き込み(3, "\220\240@\6\371\341\277>\0\2402\24\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
26882 10:38:41.920558 lseek(3, 1067864064, SEEK_SET) = 1067864064
26882 10:38:41.920573 書き込み(3, "\220\240@\6\371\341\277>\0\2402\24\0\0\0\0\202\2\7\320\343\6H\26P\340\277\370\330\30e\30"..., 4096) = 4096
...

各ランダム読み取りの前に、lseek を使用して現在のファイル オフセットを特定します。

同期シーケンシャル書き込み

先ほどの方法を使って書き順をテストする

root@wilson-ubuntu:~# strace -f -tt -o /tmp/write.log -D fio -name=write -rw=write \
-direct=1 -bs=4k -size=1G -numjobs=1 -group_reporting -filename=/tmp/test.db
書き込み: (g=0): rw=書き込み、bs=4K-4K/4K-4K/4K-4K、ioengine=同期、iodepth=1
fio-2.2.10
1 プロセスを開始
ジョブ: 1 (f=1): [W(1)] [100.0% 完了] [0KB/70432KB/0KB /s] [0/17.7K/0 iops] [eta 00m:00s]
書き込み: (グループID=0、ジョブ=1): エラー= 0: pid=27005: 2019年8月14日水曜日 10:53:02
 書き込み: io=1024.0MB、bw=70238KB/s、iops=17559、runt= 14929msec
 clat (usec): 最小=43、最大=7464、平均=55.95、標準偏差=56.24
  緯度 (usec): 最小=43、最大=7465、平均=56.15、標準偏差=56.25
...
 bw (KB /s): 最小=67304、最大=72008、パーセンテージ=99.98%、平均=70225.38、標準偏差=1266.88
...

実行ステータス グループ 0 (すべてのジョブ):
 書き込み: io=1024.0MB、aggrb=70237KB/秒、minb=70237KB/秒、maxb=70237KB/秒、mint=14929ミリ秒、maxt=14929ミリ秒

ディスク統計(読み取り/書き込み):
...
 sda: ios=0/262162、マージ=0/10、ティック=0/6948、in_queue=6932、使用率=46.49%

以下が見られます:

スループットが約70Mに増加

カーネル呼び出しをもう一度見てみましょう。

root@wilson-ubuntu:~# /tmp/write.log をさらに表示
...
27046 10:54:28.194508 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\360\t\0\0\0\0\0\0\320\17\0\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.194568 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.194627 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.194687 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.194747 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.194807 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.194868 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.194928 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.194988 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195049 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195110 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195197 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195262 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195330 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195426 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195497 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195567 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195637 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195704 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195757 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195807 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195859 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195910 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.195961 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196012 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196062 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0\220\24\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196112 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0 \26\0\0\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196162 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0 \26\0\0\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196213 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0 \26\0\0\0\0\0\0\0\0\320\17\0\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196265 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0 \26\0\0\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196314 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0 \26\0\0\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196363 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0 \26\0\0\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196414 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0 \26\0\0\0\0\0\0\0\0\320\17\0\0\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196472 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0 \26\0\0\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196524 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0 \26\0\0\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
27046 10:54:28.196573 書き込み(3, "\0\0\23\0\0\0\0\0\0\300\16\0\0\0\0\0\0 \26\0\0\0\0\0\0\0\0\320\17\0\0\0\0\0"..., 4096) = 4096
...

シーケンシャル読み取りのため、ファイルオフセットを繰り返し探す必要がなく、書き込み操作に集中できます。

5. スラットインジケーター

上記のテストでは、fio テスト レポートに slat が見つかりませんでした。これは、上記がすべて同期操作であるためです。同期 I/O の場合、I/O の送信と I/O の完了は 1 つのアクションであるため、slat は実際には I/O が完了した時間です。

非同期順次書き込みの場合は、同期順次書き込みのコマンドに -ioengine=libaio を追加します。

root@wilson-ubuntu:~# fio -name=write -rw=write -ioengine=libaio -direct=1 -bs=4k -size=1G -numjobs=1 -group_reporting -filename=/tmp/test.db
書き込み: (g=0): rw=書き込み、bs=4K-4K/4K-4K/4K-4K、ioengine=libaio、iodepth=1
fio-2.2.10
1 プロセスを開始
ジョブ: 1 (f=1): [W(1)] [100.0% 完了] [0KB/119.3MB/0KB /s] [0/30.6K/0 iops] [eta 00m:00s]
書き込み: (グループID=0、ジョブ=1): エラー= 0: pid=27258: 2019年8月14日水曜日11:14:36
 書き込み: io=1024.0MB、bw=120443KB/s、iops=30110、runt= 8706msec
 スラット (usec): 最小=3、最大=70、平均= 4.31、標準偏差= 1.56
 clat (usec): 最小=0、最大=8967、平均=28.13、標準偏差=55.68
  緯度 (usec): 最小=22、最大=8976、平均=32.53、標準偏差=55.72
...
 帯域幅 (KB /秒): 最小=118480、最大=122880、パーセンテージ=100.00%、平均=120467.29、標準偏差=1525.68
...

実行ステータス グループ 0 (すべてのジョブ):
 書き込み: io=1024.0MB、aggrb=120442KB/秒、minb=120442KB/秒、maxb=120442KB/秒、mint=8706ミリ秒、maxt=8706ミリ秒

ディスク統計(読み取り/書き込み):
...
 sda: ios=0/262147、マージ=0/1、ティック=0/6576、in_queue=6568、使用率=74.32%

スラットインジケータが表示され、latはslat + clat(平均平均値)の合計にほぼ等しいことがわかります。非同期IOに切り替えた後、スループットが大幅に改善され、約120Mになりました。

VI. 結論

● fio はディスクのベースライン ツールとして使用する必要があります。マシン (物理またはクラウド) を入手したら、できるだけ早くマシンのディスクでベースライン テストを実行して、状況を明確に把握する必要があります。● この記事のすべてのテストはキャッシュをバイパスしました。実際のアプリケーションでは、キャッシュの影響を考慮する必要があります。

以上が、Linux ディスクのシーケンシャル書き込みとランダム書き込みについてご紹介した内容です。お役に立てれば幸いです。ご質問がございましたら、メッセージを残していただければ、すぐに返信いたします。また、123WORDPRESS.COM ウェブサイトをサポートしてくださっている皆様にも感謝申し上げます。
この記事が役に立ったと思われた方は、ぜひ転載していただき、出典を明記してください。ありがとうございます!

以下もご興味があるかもしれません:
  • Linux システムでルート ディレクトリのディスク領域を拡張する方法
  • Linux の Centos7 における LVM ディスク拡張の問題
  • Linux ディスク管理ソフトウェア RAID の実装原理と方法の分析と共有
  • Linuxでディスクスペースを転送する方法
  • Linux ディスクフォーマットコマンドの詳細な説明
  • Linux仮想マシンのルートパーティションディスク拡張スペースレコードの詳細な説明
  • 不明なリソースによって Linux ディスク領域が枯渇する問題の解決方法
  • Linux のディスク容量サイズを表示するコマンド
  • Linux サーバーのディスク容量を拡張する方法 (画像)
  • 2T を超える Linux ディスクで GPT パーティションを使用する方法

<<:  MySQL でトリガーを無効化および有効化するチュートリアル [推奨]

>>:  Vue でのキープアライブコンポーネントの使用例

推薦する

CSS3 フリップカード番号サンプルコード

今日会社から課題をもらったのですが、効果図は以下のとおりです。 どのような効果を実現したいかは特に決...

MySQLテーブルをコピーする方法

目次1.mysqlダンプ実行プロセス:特徴2. CSVファイルをエクスポートする(最も柔軟性が高い)...

Tomcat8はcronologを使用してCatalina.Outログを分割します

背景tomcat によって生成された catalina.out ログ ファイルが分割されていない場合...

CentOS 7にChromeブラウザをインストールする方法

この記事では、CentOS 7 に Chrome ブラウザをインストールする方法を紹介します。詳細は...

MYSQLストアドプロシージャ、つまり一般的な論理知識のポイントの要約

MySQL ストアド プロシージャ1. ストアドプロシージャ構文(フォーマット)を作成する 区切り文...

フローティング要素が親要素の高さを崩す原因と解決策の詳細な説明

フローティング要素は、親要素の高さを縮小します。要素を float float:left/right...

フロントエンドJSサンドボックスを実装するいくつかの方法についての簡単な説明

目次序文iframeはサンドボックスを実装しますdiffメソッドを使用したサンドボックスの実装プロキ...

CSS3を使って歌詞進行テキストカラー塗りつぶし変更の動的効果を実装するアイデアの詳細な説明

音楽を再生すると、曲が進むにつれて歌詞が徐々に色づきます。色は単語ごとに変わるのではなく、左から右へ...

Linux/Mac に MySQL をインストールするときにパスワードを忘れた場合の解決策

序文この記事では主に、Linux/Mac に MySQL をインストールするときにパスワードを忘れた...

MySQL インストール図の概要

MySQL 5.5 のインストールと設定方法のグラフィックチュートリアルMySQL 5.5 のインス...

40以上の美しいWebフォームデザイン例

Web フォームは、訪問者と Web サイト所有者間の主要なコミュニケーション チャネルです。フィー...

Youdaの新しいプチビューの実装

目次序文導入ライブ使いやすいルートスコープマウント要素の指定ライフサイクルコンポーネントグローバル状...

JavaScript フォーム検証の例

HTML フォームは、名前、電子メール アドレス、場所、年齢などのユーザー情報を収集するためによく使...

Dockerコンテナでユーザーを分離する方法

前回の記事「Docker コンテナの UID と GID を理解する」では、Docker コンテナ内...

Vue+SpringBoot で Alipay サンドボックス決済を実装するためのサンプルコード

まず、Alipay サンドボックスから一連のものをダウンロードします。多くのブログで取り上げられてお...