Dev Study
← コンピュータの仕組み
レッスン 11 / 13·約 14 分·第1期 コンピュータ単体の仕組み

SSDはなぜ書き込みが複雑なのか — 消せる単位が大きすぎる

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理
  7. DB保存今ここ

前回SSDが速い理由を見ました。今回はその裏側、書き込みに潜む厄介な事情を扱います。

まず結論

SSDは、読み書きは小さな単位でできるのに、消去だけは大きなかたまり単位でしかできません。この不一致が、SSDの動作を複雑にしている根本原因です。

その結果、1バイト書き換えたいだけでも内部では何倍もの書き込みが発生します。そしてデータで埋まっている割合が高いほどこの倍率が跳ね上がり、性能と寿命に響きます。

? 読む前に予測

SSD(NANDフラッシュ)で、一度に消去できる最小の単位はどれでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

読み書きはできるのに、消すのが大変

前回、SSDが速い理由を見ました。動く部品が無いので、どこを読んでも同じように速い。読むだけならこれで話は終わりです。

問題は書き込みです。

SSDが使っているNANDフラッシュメモリには、扱いにくい性質があります。

  • 読み書きは ページという単位でできる
  • 消去は ブロックという単位でしかできない(ページを多数まとめた単位。2010年の論文の典型例では4KiBのページ64枚)

そして決定的なのが、上書きができないことです。一度書いた場所に別の値を書くには、先に消さなければなりません。

つまり「4KBだけ書き換えたい」と思っても、そのページを含むブロック全体を消す必要があります。しかもそのブロックには、他の有効なデータも入っているはずです。

具体実物

書き換えが、なぜ大仕事になるのか

実際に何が起きるか追ってみます。

4KBのデータを書き換えたいとき、内部で起きること
書き換え要求4KBのデータを更新したい○ 対象は1ページの一部
上書きできないNANDは消してからでないと書けない× ブロック消去が必要
ブロックには他のデータもある他のページの有効データが同居× 全部退避が必要
退避 → 消去 → 書き戻し有効データを別ブロックへコピー○ 要求より多い書き込みが発生
↓
4KB書き換えるために、内部では何倍もの書き込みが発生する
  • ・これが「書き込み増幅(Write Amplification)」の正体
  • ・実際には、書き換えは別の空きページへ書いて古いページを無効化する方式が使われる

実際のSSDはもう少し賢く動きます。書き換えのたびにブロックを消すのではなく、空いている別のページに新しい値を書き、古いページを「無効」と記録するだけにします。

しかしこの方式では、無効なページがどんどん溜まっていきます。放置すれば空きページが尽きるので、どこかで整理が必要です。その整理がガベージコレクションです。

✓ ここまでの確認

SSDで上書きができないのはなぜですか。

抽象原理

ガベージコレクションと、書き込み増幅

無効なページが散らばったブロックを再利用するには、次の手順が必要です。

  1. そのブロックに残っている有効なデータを別の場所へ退避する
  2. ブロックを丸ごと消去する
  3. 空きブロックとして再利用する

この退避のコピーが、ホストが要求していない余分な書き込みです。

ホストが1GB書き込んだつもりでも、内部では2GB、3GBと書き込まれている。この比率を書き込み増幅(Write Amplification)と呼びます。値は1以上で、退避が要らない理想的な場合にだけ1になります。

SSDの寿命は書き込み量で決まるので、この倍率は寿命に直結します。

具体実物

空き容量が減ると、急激に悪化する

ここが実務上いちばん重要な点です。書き込み増幅は、予備領域の大きさによって劇的に変わります。

物理容量をT、利用者が使える容量をUとして、予備領域の係数を ρ = (T − U) ÷ U とします(ρ = 25%なら、利用者が使えるのは物理容量の80%)。書き込みが全体に一様ランダムに来て、GCが有効データの最も少ないブロックを選ぶ(貪欲法)という仮定のもとで、書き込み増幅Wは次の式になります(Agarwal & Marrow, 2010)。

書き込み増幅 W = ½(1+ρ)/ρ表
予備領域の係数 ρ 書き込み増幅 W
100% 1.00 倍
25% 2.50 倍
15% 3.83 倍
7% 7.64 倍
→0 発散(無限大)

ρが25%なら2.5倍で済むのに、7%まで減ると7.6倍に跳ね上がります。そしてρが0に近づくと発散します。

予備が少ないほど書き込みが重くなることの、理論的な説明です。感覚的な話ではなく、仮定を置けば式で表せる関係です。

✓ ここまでの確認

予備領域の係数ρが25%から7%に減ると、書き込み増幅はどう変化しますか(一様ランダムな書き込みを仮定したモデルで)。

具体実物

SSDの消耗は、コマンドで確認できる

自分のSSDがどれだけ書き込まれ、どれだけ消耗しているかは確認できます。

$ sudo nvme smart-log /dev/nvme0(抜粋・表示例)コマンド出力
critical_warning : 0
temperature : 41 C
percentage_used : 2%
data_units_read : 45,231,887
data_units_written : 27,091,961
host_read_commands : 512,338,921
host_write_commands : 388,201,447

data_units_written は書き込み総量ですが、そのままの数字ではありません。NVMe仕様では次のように定義されています。

書き込み総量の計算(NVMe仕様の定義)表
実バイト数 = 値 × 1000 × 512
= 値 × 512,000
 
上の例: 27,091,961 × 512,000
= 約 13.87 テラバイト
 
このSSDのTBW(保証値)が600TBなら
13.87 ÷ 600 = 約2.3%
→ percentage_used の 2% と整合する

percentage_used が寿命の消費率です。上の例では2%なので、まだ十分に余裕があります。

この章のまとめ

  • NANDフラッシュは読み書きがページ単位、消去はページを多数まとめたブロック単位。この非対称性がすべての出発点。
  • 上書きができないので、書き換えは別ページへ書いて古いページを無効化し、後でまとめて整理する(ガベージコレクション)。
  • 整理の際に有効データを退避するため、内部の書き込み量がホストの要求を上回る(書き込み増幅)。値は1以上。
  • 書き込み増幅は予備領域に強く依存する。一様ランダムな書き込みのモデルで、ρが25%で2.5倍、7%では7.6倍、0に近づくと発散する。
  • SSDにデフラグは不要かつ有害。ヘッド移動が無いので効果がなく、寿命を削るだけ。代わりにTRIMを使う。
  • nvme smart-log で消耗を確認できる。data_units_written × 512,000 が実バイト数。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

環境:

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 4正解: 0

SSD(NAND型フラッシュメモリ)の読み書きと消去の単位について正しいものはどれですか。

用語集(5語)
ページ / ブロック
ページは読み書きの単位。ブロックは消去の単位で、ページを多数まとめたもの(2010年の論文の典型例は4KiBのページ64枚)。この単位の違いがSSD設計の根本制約。
ガベージコレクション (GC)
使用済みページが散らばったブロックから有効データを別の場所へ退避させ、ブロックを丸ごと消して再利用可能にする処理。
書き込み増幅 (Write Amplification)
ホストが要求した書き込み量に対する、SSD内部の実際の書き込み量の比。1以上。予備領域が少ないほど増大する。
TRIM
OSがSSDに「この領域はもう不要」と伝える命令。これが無いとSSDは削除済みデータを有効と誤認し、無駄な退避を続ける。仕様上は助言的で、必ず実行される保証はない。
TBW
Total Bytes Written。そのSSDが保証する総書き込み量。寿命の目安になる。