Skilore

ストレージ容量と単位

「ギガバイト」と「ギビバイト」の違いを正確に説明できないエンジニアが、ペタバイト規模のシステムを設計することはできない。

117 分で読めます58,332 文字

ストレージ容量と単位

「ギガバイト」と「ギビバイト」の違いを正確に説明できないエンジニアが、ペタバイト規模のシステムを設計することはできない。

この章で学ぶこと

  • ビットとバイトの定義、および歴史的背景を説明できる
  • 2進接頭辞(KiB, MiB, GiB)と10進接頭辞(KB, MB, GB)の違いを正確に区別できる
  • 各種データ(テキスト・画像・音声・動画)の典型的なサイズを見積もれる
  • システム設計における容量計算(Back-of-the-envelope estimation)ができる
  • 帯域幅・転送時間・ストレージコストの概算を素早く行える
  • 階層型ストレージの設計原則を説明できる

前提知識


1. ビットとバイト — 情報量の最小単位

1.1 ビット(bit)の定義

ビット(binary digit の略)は、情報理論における最小単位である。Claude Shannon が 1948 年の論文 "A Mathematical Theory of Communication" で定式化した概念で、2つの状態(0 または 1)のうち1つを表現する。

ビットの本質:

  1 bit = 2つの状態のうち1つを特定するための情報量

  物理的な実装例:
メディア状態 0状態 1
電圧(TTL)0-0.8V2.0-5.0V
磁気ディスクS極→N極N極→S極
光ディスクピットなしピットあり
DRAM放電充電
Flash (SLC)高閾値低閾値
光ファイバー光なし光あり
n ビットで表現可能な状態数 = 2^n
  ──────────────────────────────
  1 bit  → 2 状態       (0, 1)
  2 bits → 4 状態       (00, 01, 10, 11)
  3 bits → 8 状態       (000 ... 111)
  8 bits → 256 状態     (00000000 ... 11111111)
  16 bits → 65,536 状態
  32 bits → 4,294,967,296 状態(約43億)
  64 bits → 18,446,744,073,709,551,616 状態(約1844京)

情報量の計算は対数で表現される。ある事象の発生確率が p であるとき、その事象を知ることで得られる情報量は -log2(p) ビットである。

import math
 
def information_content(probability):
    """事象の情報量をビット単位で計算する"""
    if probability <= 0 or probability > 1:
        raise ValueError("確率は 0 < p <= 1 の範囲")
    return -math.log2(probability)
 
# 例: コイン投げ(表が出る確率 = 0.5)
print(f"コイン投げ: {information_content(0.5):.1f} bit")  # 1.0 bit
 
# 例: サイコロ(特定の目が出る確率 = 1/6)
print(f"サイコロ:   {information_content(1/6):.2f} bit")  # 2.58 bit
 
# 例: 英字1文字(26文字等確率 = 1/26)
print(f"英字1文字: {information_content(1/26):.2f} bit")   # 4.70 bit
 
# 例: ASCII文字(128文字等確率 = 1/128)
print(f"ASCII文字: {information_content(1/128):.2f} bit")  # 7.00 bit

1.2 バイト(byte)の定義と歴史

バイト(byte)は、多くの現代コンピュータにおけるアドレス指定可能な最小単位である。現在では 1 バイト = 8 ビットが事実上の標準であるが、歴史的には異なるサイズのバイトが存在した。

バイトサイズの歴史的変遷:

  年代        マシン                    バイトサイズ
  ─────────────────────────────────────────────────
  1950年代    IBM 7030 Stretch         可変長
  1956年      IBM 7030 設計書          "byte" の語が初出
  1963年      IBM System/360           8ビットに標準化
  1970年代    PDP-8                    12ビット語
  1970年代    PDP-10                   36ビット語
  1980年代〜  IBM PC互換機             8ビットが事実上標準
  現在        ほぼ全てのアーキテクチャ   8ビット = 1バイト

  注意: 歴史的曖昧さを避けるため、8ビットを明示する場合は
  「オクテット(octet)」という用語を使う(特にネットワーク分野)。
  RFC では "octet" が使われる。

  語源:
  - "byte" は "bit" と "bite" の中間的造語
  - Werner Buchholz(IBM)が 1956年に命名
  - "bite" との混同を避けるため "y" に変更

1.3 ワード(word)とアドレッシング

ワードサイズとアーキテクチャ:

  ワード = CPUが一度に処理するデータの基本単位
アーキテクチャワード幅アドレス空間
Intel 80808 bit64 KB
Intel 808616 bit1 MB
Intel 8038632 bit4 GB
x86-6464 bit16 EB(理論値)
x86-64(現行実装)48 bit256 TB
ARM Cortex-M32 bit4 GB
AArch6464 bit256 TB〜4 PB
32ビット vs 64ビットの影響:
項目32ビット64ビット
最大メモリ4 GB16 EB(理論値)
ポインタサイズ4バイト8バイト
整数演算32ビット64ビット
メモリ効率良いポインタが倍増
プロセスあたり2-3 GB128 TB以上

1.4 ニブル・その他の単位

ビットとバイトの間の単位:

  ニブル(nibble / nybble)= 4ビット = 16進数1桁
ニブル値16進表記
00000
01015
10019
1010A
1111F
1バイト = 2ニブル = 上位ニブル + 下位ニブル

  例: 0xA7 = 1010_0111
       ^^^^   ^^^^
       上位    下位
       ニブル  ニブル

  その他の情報量単位:
単位説明
trit3状態(三進法の1桁)
dit / ban10状態(十進法の1桁)
nat自然対数ベースの情報量単位
shannonビットの別名(Shannon にちなむ)
qubit量子ビット(重ね合わせ状態)

2. 接頭辞 — 2進と10進の混乱

2.1 問題の本質

コンピュータサイエンスにおいて最も根深い混乱の1つが、容量単位の接頭辞である。1キロバイトは 1,000 バイトなのか、1,024 バイトなのか。この問題は単なる学術的議論ではなく、ストレージ購入時の「容量詐欺」訴訟にまで発展した歴史がある。

混乱の原因:

  10進接頭辞(SI接頭辞):
    kilo  = 10^3  = 1,000
    mega  = 10^6  = 1,000,000
    giga  = 10^9  = 1,000,000,000
    tera  = 10^12 = 1,000,000,000,000

  2進の慣習:
    "kilo" = 2^10 = 1,024          (2.4% 大きい)
    "mega" = 2^20 = 1,048,576      (4.9% 大きい)
    "giga" = 2^30 = 1,073,741,824  (7.4% 大きい)
    "tera" = 2^40 = 約1.0995 x 10^12(10.0% 大きい)

  差のスケール:
接頭辞10進値2進値
K / Ki1,0001,024+2.4%
M / Mi1,000,0001,048,576+4.9%
G / Gi1,000,000,0001,073,741,824+7.4%
T / Ti10^122^40+10.0%
P / Pi10^152^50+12.6%
E / Ei10^182^60+15.3%
→ 単位が大きくなるほど差が拡大する
  → 1 TB の HDD は OS 上で約 931 GiB と表示される

2.2 IEC 2進接頭辞(1998年制定)

1998年、国際電気標準会議(IEC)は混乱を解消するため、2進接頭辞を正式に制定した(IEC 60027-2)。

IEC 2進接頭辞:
接頭辞記号語源
kibiKi2^10kilo + binary
mebiMi2^20mega + binary
gibiGi2^30giga + binary
tebiTi2^40tera + binary
pebiPi2^50peta + binary
exbiEi2^60exa + binary
zebiZi2^70zetta + binary
yobiYi2^80yotta + binary
正しい表記:
  - RAM 16 GiB(2進: 16 x 2^30 = 17,179,869,184 バイト)
  - HDD 1 TB (10進: 1 x 10^12 = 1,000,000,000,000 バイト)
  - SSD 512 GB(10進: 512 x 10^9 = 512,000,000,000 バイト)

2.3 業界ごとの使い分け

各業界・ソフトウェアでの接頭辞の使用状況:

  10進接頭辞(SI, 1000の累乗)を使用:
- HDD / SSD メーカー(容量表記)
- ネットワーク帯域幅(Mbps, Gbps)
- 通信キャリア(データプラン: 3GB, 20GB)
- macOS(10.6 Snow Leopard 以降)
- Ubuntu / GNOME
- iOS / iPadOS
- HDDメーカー(Western Digital, Seagate)
2進接頭辞(1024の累乗)を使用:
- RAM(メモリモジュールの容量)
- Windows(エクスプローラーのファイルサイズ表示)
- Linux カーネル(dmesg 等)
- JEDEC メモリ規格
- 多くのプログラミング言語の標準ライブラリ
IEC 2進接頭辞(KiB, MiB, GiB)を明示使用:
- GNU coreutils(ls -lh --si vs デフォルト)
- Wikipedia
- IEEE / IEC 規格文書
- 一部の Linux ディストリビューション
- systemd / journalctl

2.4 「消えた容量」問題

HDD/SSD購入時の「容量が少ない」問題:

  購入した容量: 1 TB(メーカー表記、10進)
  = 1,000,000,000,000 バイト

  OSでの表示(2進):
  = 1,000,000,000,000 / 1,073,741,824
  = 931.32 GiB

  → 約 69 GiB(約7%)が「消えた」ように見える

  さらにファイルシステムのオーバーヘッドを考慮:
  - パーティションテーブル:     数MB
  - ファイルシステムメタデータ:  全体の1-5%
  - 予約ブロック(ext4):       5%(デフォルト)
  - SSD のオーバープロビジョニング: 7-28%

  購入容量と利用可能容量の対応表:
メーカー表記OS表示(2進)実効容量(概算)
128 GB119 GiB110-115 GiB
256 GB238 GiB220-230 GiB
512 GB476 GiB440-460 GiB
1 TB931 GiB860-900 GiB
2 TB1,862 GiB1,720-1,800 GiB
4 TB3,725 GiB3,450-3,600 GiB
訴訟の歴史:
  - 2006年: Western Digital が集団訴訟で和解
  - 消費者に対してデータ復旧ソフトを無償提供
  - 以降、多くのメーカーがパッケージに注釈を記載
    「1GB = 1,000,000,000 bytes」

2.5 単位変換の実装

"""ストレージ容量の単位変換ユーティリティ"""
 
# --- 2進接頭辞(IEC)---
KiB = 1024
MiB = 1024 ** 2     # 1,048,576
GiB = 1024 ** 3     # 1,073,741,824
TiB = 1024 ** 4     # 1,099,511,627,776
PiB = 1024 ** 5
EiB = 1024 ** 6
 
# --- 10進接頭辞(SI)---
KB = 1000
MB = 1000 ** 2      # 1,000,000
GB = 1000 ** 3      # 1,000,000,000
TB = 1000 ** 4      # 1,000,000,000,000
PB = 1000 ** 5
EB = 1000 ** 6
 
def human_readable_binary(size_bytes: int) -> str:
    """バイト数を2進接頭辞の人間可読形式に変換する"""
    units = [
        (EiB, "EiB"), (PiB, "PiB"), (TiB, "TiB"),
        (GiB, "GiB"), (MiB, "MiB"), (KiB, "KiB"),
    ]
    for threshold, unit in units:
        if size_bytes >= threshold:
            return f"{size_bytes / threshold:.2f} {unit}"
    return f"{size_bytes} B"
 
def human_readable_decimal(size_bytes: int) -> str:
    """バイト数を10進接頭辞の人間可読形式に変換する"""
    units = [
        (EB, "EB"), (PB, "PB"), (TB, "TB"),
        (GB, "GB"), (MB, "MB"), (KB, "KB"),
    ]
    for threshold, unit in units:
        if size_bytes >= threshold:
            return f"{size_bytes / threshold:.2f} {unit}"
    return f"{size_bytes} B"
 
# --- 使用例 ---
hdd_capacity = 1 * TB   # メーカー表記 1 TB
print(f"HDD容量(10進): {human_readable_decimal(hdd_capacity)}")
# => HDD容量(10進): 1.00 TB
print(f"HDD容量(2進):  {human_readable_binary(hdd_capacity)}")
# => HDD容量(2進):  931.32 GiB
 
ram_capacity = 16 * GiB  # RAM 16 GiB
print(f"RAM容量(2進):  {human_readable_binary(ram_capacity)}")
# => RAM容量(2進):  16.00 GiB
print(f"RAM容量(10進): {human_readable_decimal(ram_capacity)}")
# => RAM容量(10進): 17.18 GB

3. SI接頭辞の全体像

3.1 小さい方から大きい方まで

SI接頭辞(国際単位系)の完全なリスト:

  小さい側(データでは主にビットレート等で使用):
接頭辞記号10^n日本語名
quectoq10^-30クエクト
rontor10^-27ロント
yoctoy10^-24ヨクト
zeptoz10^-21ゼプト
attoa10^-18アト
femtof10^-15フェムト
picop10^-12ピコ
nanon10^-9ナノ
microu10^-6マイクロ
millim10^-3ミリ
大きい側(ストレージ容量で直接使用):
接頭辞記号10^n代表的な使用例
kiloK / k10^3テキストファイル
megaM10^6写真、MP3
gigaG10^9映画、RAM
teraT10^12HDD、年間ログ
petaP10^15大規模DB、データレイク
exaE10^18クラウド全体
zettaZ10^21世界の年間データ生成量
yottaY10^24(現時点で理論的)
ronnaR10^27(2022年に追加)
quettaQ10^30(2022年に追加)
2022年11月の第27回国際度量衡総会(CGPM)で
  ronna / quetta / ronto / quecto の4つが追加された。

3.2 データ量のスケール感

各スケールの直感的な理解:

  1 B     = 英字1文字
  1 KB    = 短いテキストファイル(パラグラフ数個分)
  1 MB    = 小説1冊分のテキスト / MP3 1分
  1 GB    = 映画1本(SD画質) / CD 約1.5枚分
  1 TB    = 印刷した紙に換算して約4500万ページ
  1 PB    = 約2000年分の MP3 音楽 / Netflix 全カタログ
  1 EB    = 全人類が2日間に生成するデータ量(概算)
  1 ZB    = 世界のインターネットトラフィック約半年分
  1 YB    = 全人類の歴史上のデータ量合計の数倍

  宇宙規模の比喩:
単位比喩
1 KBごく短い手紙
1 MB厚めの本1冊
1 GB小さな図書館の本棚1つ
1 TB大学図書館の蔵書全体
1 PB国立国会図書館の蔵書全体(推定)
1 EB全世界の図書館を合わせた規模
1 ZB地球上の砂粒の数に匹敵
1 YB観測可能な宇宙の原子数の...まだ遠い
参考: 観測可能な宇宙の原子数は約 10^80
       1 YB = 10^24 バイト = 8 x 10^24 ビット
       → 宇宙の原子数には56桁も足りない

4. データサイズの直感

4.1 テキストデータ

テキストの容量 — エンコーディング別:

  ASCII(英数字):
    1文字 = 1バイト(7ビット + パリティ or 0パディング)
    英文1ページ(約250語 / 約1500文字)= 約1.5 KB
    英語小説1冊(約8万語 / 約50万文字)= 約500 KB

  UTF-8(可変長):
    ASCII互換文字:  1バイト(U+0000-U+007F)
    ラテン拡張:     2バイト(U+0080-U+07FF)
    日本語・中国語: 3バイト(U+0800-U+FFFF)
    絵文字:        4バイト(U+10000-U+10FFFF)

  UTF-16(Javaの内部表現、Windowsの内部API):
    BMP文字:       2バイト
    補助文字:      4バイト(サロゲートペア)

  UTF-32:
    全文字:        4バイト(固定長)

  日本語テキストの容量:
コンテンツ文字数UTF-8サイズ
ツイート1件140文字約420 B
メール本文500文字約1.5 KB
ブログ記事3,000文字約9 KB
新書1冊10万文字約300 KB
長編小説30万文字約900 KB
漫画1巻(テキスト)3,000文字約9 KB
六法全書約900万文字約27 MB
プログラミングにおけるテキストデータ:
データ種別典型的サイズ
JSON APIレスポンス(小)1-10 KB
JSON APIレスポンス(大)100 KB-1 MB
ログ1行100 B-1 KB
アプリログ1日分100 MB-10 GB
RDB 1レコード(小)100 B-1 KB
RDB 1レコード(大)1-10 KB
CSV 100万行50-500 MB
ソースコード1ファイル1-50 KB
中規模プロジェクト全体1-100 MB
Linux カーネルソース約1.3 GB

4.2 画像データ

画像の容量 — フォーマット比較:

  非圧縮画像のサイズ計算:
  サイズ = 幅 x 高さ x 色深度(バイト) + ヘッダ

  例: 1920x1080、24ビットカラー(RGB各8ビット)
  = 1920 x 1080 x 3 = 6,220,800 B = 約5.93 MiB

  フォーマット別の容量比較(1920x1080 写真):
フォーマットサイズ圧縮率特徴
BMP(非圧縮)5.93 MB1:1非圧縮
PNG2-4 MB1.5-3:1可逆
JPEG(品質85)300-600KB10-20:1非可逆
JPEG(品質50)100-250KB25-60:1非可逆
WebP200-400KB15-30:1非可逆
AVIF150-300KB20-40:1非可逆
JPEG XL150-350KB17-40:1可逆/非可逆
解像度別の典型的サイズ(JPEG品質85):
解像度画素数サイズ
アイコン 32x321 K2-5 KB
サムネイル 200x20040 K10-30 KB
SNSアバター 400x400160 K30-80 KB
Web画像 800x600480 K60-150 KB
HD 1280x720921 K150-400 KB
Full HD 1920x10802.07 M300-600 KB
4K 3840x21608.29 M1-3 MB
8K 7680x432033.18 M5-15 MB
RAW 6000x400024 M25-50 MB
Web開発での画像最適化目安:
用途目標サイズ
ユーザーアバター50-200 KB
EC商品画像100-500 KB
ヒーロー画像200 KB-1 MB
LP/バナー200 KB-2 MB
ページ全体の画像計目標: 1 MB 以下

4.3 音声データ

音声の容量:

  非圧縮音声のサイズ計算:
  サイズ = サンプリングレート x ビット深度 x チャンネル数 x 秒数 / 8

  例: CD品質(44.1 kHz, 16 bit, ステレオ, 1秒)
  = 44,100 x 16 x 2 x 1 / 8 = 176,400 B = 約172 KiB/秒

  品質レベル別:
品質Hzbitchレート
電話8k818 KB/s
AM ラジオ22k16144 KB/s
FM ラジオ32k162128 KB/s
CD44.1k162172 KB/s
DVD Audio96k242576 KB/s
ハイレゾ192k2421,152 KB/s
コーデック別容量(4分間の楽曲):
フォーマットビットレート4分のサイズ圧縮率
WAV(非圧縮)1,411kbps42 MB1:1
FLAC(可逆)700-100021-30 MB1.5-2:1
AAC 256kbps256 kbps7.7 MB5.5:1
MP3 320kbps320 kbps9.6 MB4.4:1
MP3 128kbps128 kbps3.8 MB11:1
Opus 128kbps128 kbps3.8 MB11:1
Opus 64kbps64 kbps1.9 MB22:1
Codec2(音声)2.4 kbps72 KB588:1
ストリーミングサービスの品質設定:
サービス通常品質高品質
SpotifyAAC 128kbpsOGG 320kbps
Apple MusicAAC 256kbpsALAC(可逆)
YouTube MusicAAC 128kbpsAAC 256kbps
Amazon Music HDAAC 256kbpsFLAC 24bit/192k

4.4 動画データ

動画の容量:

  非圧縮動画のサイズ計算:
  サイズ = 幅 x 高さ x 色深度(B) x フレームレート x 秒数

  例: 1080p, 30fps, 24bit色, 1秒
  = 1920 x 1080 x 3 x 30 = 186,624,000 B = 約178 MiB/秒

  → 1分間の非圧縮 1080p = 約 10.4 GiB
  → 映画2時間分 = 約 1.25 TiB
  → 圧縮なしでは保存も転送も不可能

  解像度 x コーデック別容量(1分あたり):
解像度H.264H.265AV1
480p8 MB5 MB3 MB
720p20 MB12 MB8 MB
1080p45 MB25 MB17 MB
4K130 MB70 MB45 MB
8K500 MB250 MB160 MB
※ 数値は一般的なビットレート設定での目安

  配信サービスの帯域幅:
サービス品質帯域幅
YouTube 360pSD0.7 Mbps
YouTube 720pHD2.5 Mbps
YouTube 1080pFull HD5 Mbps
YouTube 4K4K20 Mbps
Netflix SDSD1 Mbps
Netflix HDHD5 Mbps
Netflix 4K HDR4K15-25 Mbps
Zoom 音声のみ-0.1 Mbps
Zoom 720pHD1.5 Mbps
Zoom 1080pFull HD3 Mbps
動画ストレージの見積もり例:
コンテンツサイズ
30秒プロモ動画(Web用)5-20 MB
YouTube 10分動画100-500 MB(元素材)
1時間ウェビナー500 MB-2 GB
映画1本 Blu-ray25-50 GB
映画1本 4K UHD50-100 GB
Netflix 全カタログ推定 10 PB 以上

5. ストレージメディアの物理特性

5.1 ストレージ技術の階層

ストレージ階層(速度 vs 容量 vs コスト):

  速い・高価・小容量
  ^
  |  CPU レジスタ     : 数百B   , < 1ns   , $$$$$$$
  |  L1 キャッシュ    : 32-64KB , 1ns     , $$$$$$
  |  L2 キャッシュ    : 256KB-1MB, 4ns    , $$$$$
  |  L3 キャッシュ    : 数MB-数十MB, 20ns , $$$$
  |  メインメモリ(DDR5): 数GB-数TB, 100ns , $$$
  |  NVMe SSD        : 数百GB-数TB, 10-100us, $$
  |  SATA SSD        : 数百GB-数TB, 50-200us, $$
  |  HDD             : 数TB-20TB, 2-10ms  , $
  |  テープ(LTO-9)   : 18TB/巻 , 数秒-数分, c
  |  光ディスク       : 25-128GB, 数秒    , c
  v
  遅い・安価・大容量
メディア容量/デバイススループット$/GB
DDR5 DIMM16-256 GB50 GB/s$3-5
NVMe Gen5 SSD1-8 TB12 GB/s$0.08-0.15
SATA SSD256GB-4 TB550 MB/s$0.05-0.10
HDD (CMR)2-24 TB200 MB/s$0.015-0.03
HDD (SMR)4-20 TB150 MB/s$0.012-0.025
LTO-9 テープ18 TB400 MB/s$0.005
Blu-ray 4層128 GB72 MB/s$0.01
DNA Storage理論: 215PB/g極めて遅い研究段階

5.2 記憶装置のIOPS比較

IOPS(1秒あたりの入出力操作数)比較:
デバイス読み取りIOPS書き込みIOPSレイテンシ
HDD 7200rpm100-200100-2002-10 ms
HDD 15000rpm200-400200-4002-4 ms
SATA SSD50K-100K30K-90K50-200 us
NVMe SSD500K-1.5M200K-1M10-50 us
Intel Optane500K-600K200K-500K7-10 us
RAM Disk数百万数百万< 1 us
計算例: DBの1トランザクションに10回のランダムI/Oが必要な場合
  - HDD:     100 IOPS / 10 = 10 TPS
  - SATA SSD: 80,000 IOPS / 10 = 8,000 TPS
  - NVMe SSD: 800,000 IOPS / 10 = 80,000 TPS

  → SSDへの移行だけでDBスループットが100-800倍向上する

5.3 ストレージ容量の歴史的推移

記憶容量の進化:

  年    デバイス                     容量         $/GB(当時)
  ──────────────────────────────────────────────────────────
  1956  IBM 350 (初のHDD)           5 MB         $200,000
  1969  IBM 2314                    29 MB        $10,000
  1980  Seagate ST-506 (初の5.25")  5 MB         $5,000
  1983  IBM PC/XT                   10 MB        $3,500
  1988  初の100MB HDD               100 MB       $100
  1991  初の1GB HDD                 1 GB         $10
  1997  初の10GB HDD                10 GB        $4
  2000  初の100GB HDD               100 GB       $1
  2007  初の1TB HDD                 1 TB         $0.30
  2009  初の2TB HDD                 2 TB         $0.10
  2019  16TB HDD(Seagate Exos)    16 TB        $0.025
  2023  30TB HDD(SMR)             30 TB        $0.015
  2025  HDD ロードマップ            40-50 TB     -

  クライダーの法則(Kryder's Law):
  「HDDの面積あたり記録密度は13ヶ月ごとに倍増する」
  → ムーアの法則のストレージ版
  → 2010年代以降、鈍化傾向にある
  → HAMR/MAMR 等の新技術で再加速の可能性

  SSD の進化:
  年    容量              備考
  ──────────────────────────────────────
  2006  32 GB             初期の消費者向けSSD
  2009  256 GB            SLC/MLC
  2012  1 TB              Samsung 840 EVO 系
  2016  4 TB              Samsung 850 EVO
  2018  8 TB              Samsung 870 QVO
  2020  16 TB             エンタープライズ向け
  2023  32 TB             Solidigm D5-P5336
  2024  64 TB+            QLC/PLC 大容量SSD

6. システム設計の容量見積もり

6.1 Back-of-the-Envelope Estimation の手法

システム設計面接や実際のインフラ設計で最も重要なスキルの1つが、概算(Back-of-the-envelope estimation)である。正確な数値は不要で、桁数(order of magnitude)が合っていることが重要である。

概算のための便利な近似:

  2^10 = 10^3(千)      誤差: +2.4%
  2^20 = 10^6(百万)    誤差: +4.9%
  2^30 = 10^9(十億)    誤差: +7.4%
  2^40 = 10^12(兆)     誤差: +10.0%

  時間の近似:
  1日   = 86,400秒     = 約 10^5 秒(概算で十分)
  1ヶ月 = 2,592,000秒  = 約 2.5 x 10^6 秒
  1年   = 31,536,000秒 = 約 3 x 10^7 秒 = 約 pi x 10^7 秒

  頻出する計算パターン:
1. ストレージ = DAU x 行動/日 x データサイズ
x レプリカ数 x 保持期間
2. 帯域幅 = QPS x レスポンスサイズ
3. QPS = DAU x 行動/日 / 86400
ピーク QPS = 平均 QPS x 2〜3(ピーク係数)
4. 読み書き比 = 読み取りQPS / 書き込みQPS
SNS: 100:1〜1000:1
メッセージング: 5:1〜20:1
EC: 50:1〜200:1

6.2 Twitter風サービスの容量計算

Twitter風サービスの容量見積もり:

  前提条件:
MAU(月間アクティブユーザー): 500M
DAU(日間アクティブユーザー): 300M
1人あたり平均投稿数: 2件/日
テキスト平均: 200文字(UTF-8: 400B)
メタデータ: 200B/投稿
画像添付率: 20%(平均200KB)
動画添付率: 5%(平均5MB)
Step 1: 1日の投稿数
  300M x 2 = 600M 投稿/日

  Step 2: 1日のデータ量
  テキスト+メタ: 600M x 600B      = 360 GB/日
  画像:         600M x 0.2 x 200KB = 24 TB/日
  動画:         600M x 0.05 x 5MB  = 150 TB/日
  合計:         約 174 TB/日

  Step 3: 年間ストレージ
  174 TB x 365 = 63.5 PB/年

  Step 4: レプリカとバックアップ
  レプリカ 3倍: 63.5 x 3 = 190.5 PB/年
  バックアップ加算: 約 200 PB/年

  Step 5: 5年間の保持
  200 PB x 5 = 1 EB(圧縮前)
  圧縮50%適用: 約 500 PB

  Step 6: QPS(書き込み)
  600M / 86,400 = 約 6,944 QPS(平均)
  ピーク(x3): 約 20,833 QPS

  Step 7: QPS(読み取り、比率100:1)
  読み取り平均: 694,400 QPS
  読み取りピーク: 約 2,083,000 QPS

  Step 8: 帯域幅
  書き込み: 174 TB / 86,400 = 約 2 GB/s = 約 16 Gbps
  読み取り: 2 GB/s x 100 = 約 200 GB/s = 約 1.6 Tbps

  結論:
年間ストレージ増分: 約 200 PB
5年間の総容量: 約 500 PB(圧縮後)
ピーク書き込みQPS: 約 21K
ピーク読み取りQPS: 約 2.1M
必要帯域幅: 約 1.6 Tbps(読み取り)

6.3 サービス規模別の目安

サービス規模別のインフラ目安:
規模DBストレージ帯域幅QPS
個人ブログ100 MB10 GB10 Mbps1-10
小規模SaaS1 GB100 GB50 Mbps10-100
スタートアップ10 GB1 TB100Mbps100-1K
中規模1 TB100 TB10 Gbps1K-100K
大規模100 TB10 PB1 Tbps100K-10M
FAANG級10 PB+1 EB+100Tbps10M+

7. レイテンシの数字

7.1 プログラマが知るべきレイテンシ

Jeff Dean が Google で整理した "Numbers Every Programmer Should Know" は、システム設計の基礎知識として広く知られている。

レイテンシの比較(2024年版の概算値):

  操作                              時間          比喩
  ──────────────────────────────────────────────────────
  L1 キャッシュ参照                  1 ns         心臓の鼓動1回
  分岐予測ミス                      3 ns
  L2 キャッシュ参照                  4 ns
  ミューテックスのロック/アンロック    17 ns
  L3 キャッシュ参照                  20 ns
  メインメモリ参照                   100 ns       まばたき
  1 KB の Snappy 圧縮               2,000 ns
  SSD ランダム読み取り               16,000 ns    くしゃみ
  1 MB メモリからの逐次読み取り       3,000 ns
  1 MB SSD からの逐次読み取り         49,000 ns
  1 MB HDD からの逐次読み取り         825,000 ns
  同一DC内ラウンドトリップ            500,000 ns   深呼吸
  HDD ディスクシーク                 2,000,000 ns
  パケット CA→NL→CA               150,000,000 ns 昼寝

  覚えておくべき比率:
比較対象倍率
メモリ vs SSD ランダム読取り約 160倍
SSD vs HDD ランダム読取り約 125倍
メモリ vs HDD約 20,000倍
DC内 vs 大陸間約 300倍
1MB メモリ vs 1MB SSD約 16倍
1MB SSD vs 1MB HDD約 17倍

7.2 レイテンシの「人間スケール」変換

もし 1 ns = 1秒 だったら:

  L1 キャッシュ参照:       1秒          → 心拍1回
  L2 キャッシュ参照:       4秒          → 深呼吸1回
  L3 キャッシュ参照:       20秒         → エレベータ待ち
  メインメモリ参照:        1分40秒      → お茶を一杯淹れる
  SSD ランダム読取り:      4時間26分    → 映画2本
  HDD ディスクシーク:      23日         → 海外旅行
  同一DC内通信:            5日18時間    → 1週間の出張
  大陸間通信:              4年9ヶ月     → 大学卒業
  5秒の画面表示待ち:       158年        → 人生2周分
この比喩から得られる教訓:
1. キャッシュミスは「秒」が「分」になる感覚
2. ディスクI/Oは「秒」が「日」になる感覚
3. ネットワーク呼び出しは「秒」が「年」の感覚
4. だからキャッシュとバッチ処理が重要

8. 帯域幅の計算

8.1 ビット毎秒とバイト毎秒

ネットワーク帯域幅の最も重要な注意点は、ネットワーク速度が bit/s で表記され、ファイルサイズが byte で表記されることである。この変換を間違えると、転送時間の見積もりが8倍ずれる。

帯域幅の単位変換:

  基本: 1 byte = 8 bits
  → 1 Gbps = 1,000,000,000 bits/s
           = 125,000,000 bytes/s
           = 125 MB/s
           = 約119 MiB/s

  ネットワーク接続の理論値と実効値:
接続種別理論最大実効帯域幅実効(MB/s)
4G LTE150 Mbps10-501.25-6.25
5G Sub-61 Gbps100-50012.5-62.5
5G mmWave10 Gbps1-4 Gbps125-500
WiFi 5 (ac)3.5 Gbps200-80025-100
WiFi 6 (ax)9.6 Gbps500-200062.5-250
WiFi 7 (be)46 Gbps1-8 Gbps125-1000
GbE1 Gbps900 Mbps112
10GbE10 Gbps9.5 Gbps1187
25GbE25 Gbps24 Gbps3000
100GbE100 Gbps98 Gbps12250
オーバーヘッドの内訳:
  - Ethernet フレーム:    約3%(プリアンブル、IFG、CRC)
  - IP ヘッダ:           20-60 バイト/パケット
  - TCP ヘッダ:          20-60 バイト/パケット
  - TLS:                 数十バイト + ハンドシェイク
  - アプリケーション層:   可変
  - 合計オーバーヘッド:   小パケットで30-50%、大パケットで3-5%

8.2 転送時間の計算

"""転送時間の計算ツール"""
 
def transfer_time(size_bytes: int, bandwidth_mbps: float,
                  overhead_pct: float = 10.0) -> dict:
    """
    ファイル転送時間を計算する。
 
    Args:
        size_bytes: ファイルサイズ(バイト)
        bandwidth_mbps: 帯域幅(Mbps)
        overhead_pct: プロトコルオーバーヘッド(%)
 
    Returns:
        辞書(秒数と人間可読形式)
    """
    effective_bps = bandwidth_mbps * 1_000_000 * (1 - overhead_pct / 100)
    effective_Bps = effective_bps / 8
    seconds = size_bytes / effective_Bps
 
    if seconds < 60:
        human = f"{seconds:.1f}秒"
    elif seconds < 3600:
        human = f"{seconds / 60:.1f}分"
    elif seconds < 86400:
        human = f"{seconds / 3600:.1f}時間"
    else:
        human = f"{seconds / 86400:.1f}日"
 
    return {
        "seconds": round(seconds, 2),
        "human": human,
        "effective_MBps": round(effective_Bps / 1_000_000, 2),
    }
 
# --- 転送時間の比較表を生成 ---
files = [
    ("Webページ",    2 * 10**6),
    ("楽曲1曲",      4 * 10**6),
    ("HD映画",       5 * 10**9),
    ("ゲーム",       50 * 10**9),
    ("バックアップ",  1 * 10**12),
]
 
bandwidths = [10, 100, 1000]  # Mbps
 
print(f"{'ファイル':12s}", end="")
for bw in bandwidths:
    print(f"  {bw} Mbps", end="")
print()
print("-" * 60)
 
for name, size in files:
    print(f"{name:12s}", end="")
    for bw in bandwidths:
        result = transfer_time(size, bw)
        print(f"  {result['human']:>10s}", end="")
    print()
 
# 出力例:
# ファイル        10 Mbps  100 Mbps  1000 Mbps
# ------------------------------------------------------------
# Webページ        1.8秒      0.2秒      0.0秒
# 楽曲1曲          3.6秒      0.4秒      0.0秒
# HD映画          44.4分      4.4分      0.4分
# ゲーム           7.4時間    44.4分      4.4分
# バックアップ      3.1日      7.4時間    44.4分

8.3 Sneakernet — 物理転送の帯域幅

「トラック一杯のテープの帯域幅を舐めてはいけない」
  — Andrew Tanenbaum

  物理転送 vs ネットワーク転送の比較:

  シナリオ: 1 PB のデータを転送する

  ネットワーク経由:
    10 Gbps 回線: 1 PB / 1.25 GB/s = 800,000 秒 = 約 9.3 日
    100 Gbps回線: 1 PB / 12.5 GB/s = 80,000 秒 = 約 22 時間

  物理転送:
    18TB LTO-9テープ x 56本 = 約 1 PB
    重量: 約15 kg
    翌日配送で到着: 86,400秒
    実効帯域幅: 1 PB / 86,400 = 11.6 GB/s = 約 93 Gbps

  → 10 Gbps回線より物理輸送の方が10倍速い
  → ただしレイテンシは24時間

  AWS の物理転送サービス:
サービス容量用途
AWS Snowcone8-14 TBエッジ/IoT
AWS Snowball80 TBデータ移行
AWS Snowball Edge80-210TBエッジコンピュート
AWS Snowmobile100 PBエクサバイト級移行
Snowmobile は文字通り45フィートのトレーラーであり、
  専用のネットワーク機器と電力設備を搭載している。

8.4 Webパフォーマンス予算

Webパフォーマンス予算の設計:

  目標: 3G モバイル環境(1.5 Mbps)で3秒以内に LCP 到達

  転送可能データ量:
  3秒 x 1.5 Mbps / 8 = 562 KB

  この 562 KB を各リソースに配分する:
リソース予算備考
HTML30 KBgzip圧縮後
CSS50 KBgzip圧縮後
JavaScript200 KBgzip圧縮後(約800KB展開後)
フォント80 KBwoff2 サブセット
画像200 KBWebP / AVIF
合計560 KB<= 予算562KB
JavaScript の隠れたコスト:
gzip 200KB → 展開後 約 800KB
→ パース時間(モバイルCPU): 0.5-2秒
→ コンパイル時間: 0.2-1秒
→ 実行時間: 可変
合計: 転送3秒 + パース/実行2-5秒 = 5-8秒の体感
→ JS の「真のコスト」はサイズだけではない
Core Web Vitals の目標値(Google推奨):
指標GoodNeeds ImpPoor
LCP<= 2.5秒<= 4.0秒> 4.0秒
INP<= 200ms<= 500ms> 500ms
CLS<= 0.1<= 0.25> 0.25

9. データセンター規模のスケール

9.1 主要サービスのデータ量

世界規模のデータ量(概算):

  Google:
検索インデックス: 100 PB 以上
Gmail: 15 EB+(30億ユーザー)
YouTube: 毎分500時間のアップロード
→ 1日720,000時間分の新規動画
Google Photos: 1日40億枚のアップロード
Google Maps: 20 PB+(衛星/ストリート)
Meta:
Facebook + Instagram: 1日あたり数百TB生成
Instagram: 1日1億枚以上の写真
WhatsApp: 1日1000億通のメッセージ
データウェアハウス: 300+ PB(Hive)
Netflix:
カタログ総容量: 10 PB+(多解像度x多言語)
CDN配信量: ピーク時ネット帯域の15%
Open Connect CDN: 世界中に数千台のサーバー
世界全体:
2020年の年間データ生成量: 約 64 ZB
2025年の年間データ生成量: 約 180 ZB(予測)
2030年の年間データ生成量: 約 600+ ZB(予測)
1 ZB = 10^21 バイト
= 1,000 EB
= 1,000,000 PB
= 1,000,000,000 TB

9.2 ストレージコストの比較

ストレージコスト比較表(概算):
メディア$/TB/月主な用途
DRAM メモリ$3,000キャッシュ、インメモリDB
NVMe SSD$50ホットデータ、OLTP
SATA SSD$20ウォームデータ
HDD$5コールドデータ、ログ
S3 Standard$23クラウドホットストレージ
S3 IA$12.5低頻度アクセス
S3 Glacier$4アーカイブ(分〜時間)
S3 Deep Archive$1長期保存(12時間復元)
LTO-9 テープ$0.5オフラインアーカイブ
コスト比較の視覚化(対数スケール):
  DRAM    |████████████████████████████████████| $3000
  NVMe    |██                                  | $50
  SATA SSD|█                                   | $20
  HDD     |                                    | $5
  S3 Std  |█                                   | $23
  S3 IA   |█                                   | $12.5
  Glacier |                                    | $4
  Deep Arc|                                    | $1
  テープ  |                                    | $0.5

  → DRAM は HDD の約600倍のコスト
  → 適切な階層化設計がコスト最適化の鍵

9.3 階層型ストレージ設計

階層型ストレージ(Tiered Storage)の設計原則:
ホット層(5%のデータ、80%のアクセス)
┌─────────────────────────────────────┐
NVMe SSD / Redis / Memcached
直近24時間のデータ
アクセス頻度: 毎秒〜毎分
└─────────────────────────────────────┘
ウォーム層(15%のデータ、15%のアクセス)
┌─────────────────────────────────────┐
SATA SSD / S3 Standard / HDD
直近30日のデータ
アクセス頻度: 毎時〜毎日
└─────────────────────────────────────┘
コールド層(40%のデータ、4%のアクセス)
┌─────────────────────────────────────┐
S3 IA / HDD アレイ
直近1年のデータ
アクセス頻度: 月に数回
└─────────────────────────────────────┘
アーカイブ層(40%のデータ、1%のアクセス)
┌─────────────────────────────────────┐
Glacier / テープ / Deep Archive
1年以上前のデータ
アクセス頻度: 年に数回(災害復旧等)
└─────────────────────────────────────┘
コスト最適化の計算例:
  100 TB のデータを保持する場合

  全てS3 Standard: 100 TB x $23/TB = $2,300/月

  階層化した場合:
    ホット(5TB)     x $50   = $250
    ウォーム(15TB)  x $23   = $345
    コールド(40TB)  x $12.5 = $500
    アーカイブ(40TB)x $1    = $40
    合計: $1,135/月

  → 約51%のコスト削減

10. 容量見積もりの実装パターン

10.1 容量見積もりクラス

"""システム設計における容量見積もりの自動計算"""
 
from dataclasses import dataclass
from typing import Optional
 
@dataclass
class ServiceEstimation:
    """サービスの容量見積もりを計算するクラス"""
    name: str
    dau: int                        # 日間アクティブユーザー
    actions_per_user_per_day: float  # 1ユーザーあたりの日次アクション数
    avg_payload_bytes: int           # 1アクションの平均データサイズ
    read_write_ratio: int = 100     # 読み書き比率
    peak_factor: float = 3.0        # ピーク係数
    replication_factor: int = 3     # レプリカ数
    retention_years: int = 5        # データ保持年数
    compression_ratio: float = 0.5  # 圧縮率(0.5 = 50%圧縮)
 
    @property
    def daily_actions(self) -> float:
        return self.dau * self.actions_per_user_per_day
 
    @property
    def daily_storage_bytes(self) -> float:
        return self.daily_actions * self.avg_payload_bytes
 
    @property
    def yearly_storage_bytes(self) -> float:
        return self.daily_storage_bytes * 365
 
    @property
    def total_storage_bytes(self) -> float:
        raw = self.yearly_storage_bytes * self.retention_years
        replicated = raw * self.replication_factor
        compressed = replicated * self.compression_ratio
        return compressed
 
    @property
    def avg_write_qps(self) -> float:
        return self.daily_actions / 86400
 
    @property
    def peak_write_qps(self) -> float:
        return self.avg_write_qps * self.peak_factor
 
    @property
    def avg_read_qps(self) -> float:
        return self.avg_write_qps * self.read_write_ratio
 
    @property
    def peak_read_qps(self) -> float:
        return self.avg_read_qps * self.peak_factor
 
    @property
    def write_bandwidth_gbps(self) -> float:
        bytes_per_sec = self.daily_storage_bytes / 86400
        return bytes_per_sec * 8 / 1e9
 
    def report(self) -> str:
        """見積もりレポートを生成する"""
        def fmt(n):
            if n >= 1e18: return f"{n/1e18:.1f} EB"
            if n >= 1e15: return f"{n/1e15:.1f} PB"
            if n >= 1e12: return f"{n/1e12:.1f} TB"
            if n >= 1e9:  return f"{n/1e9:.1f} GB"
            if n >= 1e6:  return f"{n/1e6:.1f} MB"
            return f"{n:.0f} B"
 
        lines = [
            f"=== {self.name} 容量見積もり ===",
            f"DAU:              {self.dau:,}",
            f"日次アクション:   {self.daily_actions:,.0f}",
            f"",
            f"--- ストレージ ---",
            f"1日の生データ:    {fmt(self.daily_storage_bytes)}",
            f"1年の生データ:    {fmt(self.yearly_storage_bytes)}",
            f"総容量(圧縮後):   {fmt(self.total_storage_bytes)}",
            f"  ({self.retention_years}年, x{self.replication_factor}レプリカ,"
            f" {self.compression_ratio*100:.0f}%圧縮)",
            f"",
            f"--- QPS ---",
            f"平均書込QPS:      {self.avg_write_qps:,.0f}",
            f"ピーク書込QPS:    {self.peak_write_qps:,.0f}",
            f"平均読取QPS:      {self.avg_read_qps:,.0f}",
            f"ピーク読取QPS:    {self.peak_read_qps:,.0f}",
            f"",
            f"--- 帯域幅 ---",
            f"書込帯域幅:       {self.write_bandwidth_gbps:.2f} Gbps",
            f"読取帯域幅:       "
            f"{self.write_bandwidth_gbps * self.read_write_ratio:.2f} Gbps",
        ]
        return "\n".join(lines)
 
# --- 使用例 ---
twitter = ServiceEstimation(
    name="Twitter風サービス",
    dau=300_000_000,
    actions_per_user_per_day=2,
    avg_payload_bytes=600,          # テキスト + メタデータ
    read_write_ratio=100,
    peak_factor=3.0,
    replication_factor=3,
    retention_years=5,
    compression_ratio=0.5,
)
print(twitter.report())
 
instagram = ServiceEstimation(
    name="Instagram風サービス",
    dau=500_000_000,
    actions_per_user_per_day=3,
    avg_payload_bytes=2_000_000,    # 平均2MBの画像
    read_write_ratio=200,
    peak_factor=2.5,
    replication_factor=3,
    retention_years=7,
    compression_ratio=0.6,
)
print("\n" + instagram.report())

10.2 ストレージコスト計算

"""階層型ストレージのコスト最適化計算"""
 
from dataclasses import dataclass, field
 
@dataclass
class StorageTier:
    """ストレージ階層の定義"""
    name: str
    cost_per_tb_month: float    # $/TB/月
    data_percentage: float      # この階層に置くデータの割合
    access_latency: str         # アクセスレイテンシの目安
 
@dataclass
class StorageCostCalculator:
    """ストレージコストの計算"""
    total_data_tb: float
    tiers: list = field(default_factory=list)
 
    def add_tier(self, tier: StorageTier):
        self.tiers.append(tier)
 
    def calculate(self) -> dict:
        total_cost = 0
        details = []
        for tier in self.tiers:
            tier_tb = self.total_data_tb * tier.data_percentage
            tier_cost = tier_tb * tier.cost_per_tb_month
            total_cost += tier_cost
            details.append({
                "name": tier.name,
                "data_tb": tier_tb,
                "cost_month": tier_cost,
                "latency": tier.access_latency,
            })
        return {
            "total_cost_month": total_cost,
            "total_cost_year": total_cost * 12,
            "details": details,
        }
 
# --- 使用例: 100TB の階層化設計 ---
calc = StorageCostCalculator(total_data_tb=100)
calc.add_tier(StorageTier("NVMe SSD (ホット)",  50.0, 0.05, "< 1ms"))
calc.add_tier(StorageTier("S3 Standard (ウォーム)", 23.0, 0.15, "< 100ms"))
calc.add_tier(StorageTier("S3 IA (コールド)", 12.5, 0.40, "< 100ms"))
calc.add_tier(StorageTier("Glacier (アーカイブ)", 1.0, 0.40, "分〜時間"))
 
result = calc.calculate()
print(f"月間コスト:  ${result['total_cost_month']:,.0f}")
print(f"年間コスト:  ${result['total_cost_year']:,.0f}")
for d in result["details"]:
    print(f"  {d['name']:30s} {d['data_tb']:6.1f} TB  "
          f"${d['cost_month']:8,.0f}/月  遅延: {d['latency']}")
 
# 出力:
# 月間コスト:  $1,135
# 年間コスト:  $13,620
#   NVMe SSD (ホット)                5.0 TB  $     250/月  遅延: < 1ms
#   S3 Standard (ウォーム)          15.0 TB  $     345/月  遅延: < 100ms
#   S3 IA (コールド)                40.0 TB  $     500/月  遅延: < 100ms
#   Glacier (アーカイブ)            40.0 TB  $      40/月  遅延: 分〜時間

11. アンチパターン

11.1 アンチパターン1: 単位の混同による容量見積もりの崩壊

アンチパターン: GB と GiB を混同した見積もり
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  状況:
  「1TB の SSD を10台購入して 10TB のストレージクラスタを構築する」

  誤った計算:
  10台 x 1TB = 10TB → 10,000 GB の利用可能容量

  正しい計算:
  1. メーカー表記 1TB = 1,000,000,000,000 バイト(10進)
  2. OS表示: 931 GiB(2進)
  3. ファイルシステムオーバーヘッド: -5% → 884 GiB
  4. SSD オーバープロビジョニング: -7% → 822 GiB
  5. RAID 10 冗長化: 有効容量50% → 411 GiB/台
  6. 10台合計: 4,110 GiB = 約 4.01 TiB

  → 期待していた「10TB」の実質は約4TiB
  → 見積もりが約2.5倍ずれている

  教訓:
1. 常にバイト数で計算し、最後に単位変換する
2. メーカー表記(10進)とOS表示(2進)を区別する
3. FS オーバーヘッド、冗長化、OPを必ず考慮する
4. 見積もりには常に20-30%のマージンを確保する

11.2 アンチパターン2: 成長率を考慮しないストレージ設計

アンチパターン: 静的な容量設計
━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  状況:
  「現在のデータ量は 500GB だから 1TB の DB で十分だろう」

  問題点:
月次成長率 10% の場合:
現在: 500 GB
3ヶ月後: 665 GB
6ヶ月後: 885 GB
7ヶ月後: 974 GB ← 1TB に迫る
8ヶ月後: 1,071 GB ← 容量超過!
12ヶ月後: 1,569 GB
24ヶ月後: 4,926 GB
→ わずか8ヶ月で容量不足に陥る
複利成長の恐ろしさ(72の法則):
  成長率 x 倍増期間 = 72

  月次10%: 72 / 10 = 7.2ヶ月で倍増
  月次5%:  72 / 5  = 14.4ヶ月で倍増
  月次2%:  72 / 2  = 36ヶ月で倍増

  正しいアプローチ:
1. 過去6-12ヶ月の成長率を分析する
2. 少なくとも18ヶ月先の容量を見積もる
3. 容量の70%到達でアラートを設定する
4. 容量の85%到達でスケールアップ/アウトを実行する
5. 定期的な容量レビュー(四半期ごと)を行う
6. データ保持ポリシーを定めて不要データを削除する

11.3 アンチパターン3: ビット/バイト変換の見落とし

アンチパターン: ネットワーク帯域幅の単位ミス
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  状況:
  「1Gbps の回線があるから、1GB のファイルを1秒で転送できる」

  現実:
  1 Gbps = 1,000,000,000 bits/s
         = 125,000,000 bytes/s
         = 125 MB/s

  さらにプロトコルオーバーヘッド(約10%)を考慮:
  実効帯域幅 = 約 112 MB/s

  1 GB のファイル転送時間:
  1,000,000,000 / 112,000,000 = 約 8.9 秒

  → 1秒ではなく約9秒かかる(9倍の誤差)

  教訓:
1. ネットワーク = bits/s、ストレージ = bytes
2. 変換時は必ず8で割る(bits → bytes)
3. さらにプロトコルオーバーヘッド10-30%を考慮する
4. TCP のスロースタートで初期は帯域幅が出ない
5. 共有回線では他のトラフィックとの競合がある

12. 実践演習

演習1: 容量見積もり(基礎)

問題: Instagram風の写真共有サービスを設計する。以下の前提で、1年間に必要なストレージ容量を算出せよ。

  • DAU: 1,000万人
  • 1人あたり平均3枚/日のアップロード
  • 1枚の平均サイズ: 2 MB(オリジナル)
  • サムネイル: 3種類(大: 200KB, 中: 50KB, 小: 10KB)
  • レプリカ: 3倍
  • 圧縮は適用しない
解答の指針:

  Step 1: 1日のアップロード数
  10,000,000 x 3 = 30,000,000 枚/日

  Step 2: 1枚あたりの総データ量
  オリジナル: 2,000 KB
  サムネイル: 200 + 50 + 10 = 260 KB
  合計: 2,260 KB = 約 2.26 MB

  Step 3: 1日のデータ量
  30,000,000 x 2.26 MB = 67,800,000 MB = 約 67.8 TB/日

  Step 4: 1年のデータ量
  67.8 TB x 365 = 24,747 TB = 約 24.7 PB/年

  Step 5: レプリカ適用
  24.7 PB x 3 = 74.1 PB/年

  結論: 約 74 PB/年 のストレージが必要

演習2: コスト最適化(応用)

問題: 演習1のサービスのストレージを階層化し、年間コストを比較せよ。

条件:

  • 直近30日のデータ: S3 Standard($23/TB/月)
  • 30-180日のデータ: S3 IA($12.5/TB/月)
  • 180日以降: S3 Glacier($4/TB/月)
解答の指針:

  1年分の生データ: 24.7 PB(レプリカ前)

  階層別のデータ量(レプリカ3倍適用後):
  ホット(30日分):  67.8 TB x 30 x 3 = 6,102 TB = 約 6.1 PB
  ウォーム(150日分): 67.8 TB x 150 x 3 = 30,510 TB = 約 30.5 PB
  コールド(185日分): 67.8 TB x 185 x 3 = 37,629 TB = 約 37.6 PB

  月間コスト:
  ホット:    6,100 TB x $23   = $140,300
  ウォーム:  30,500 TB x $12.5 = $381,250
  コールド:  37,600 TB x $4    = $150,400
  合計: $671,950/月 = 約 $8,063,400/年

  比較: 全てS3 Standardの場合
  74,100 TB x $23 = $1,704,300/月 = 約 $20,451,600/年

  → 階層化により年間約 $12,388,200(約60%)の削減

演習3: 帯域幅とインフラ設計(発展)

問題: 演習1のサービスにおいて、以下を設計せよ。

  1. ピーク時の書き込みQPS
  2. ピーク時の読み取りQPS(読み書き比 = 200:1)
  3. 必要なCDN帯域幅
  4. CDNのキャッシュヒット率を95%とした場合のオリジン帯域幅
解答の指針:

  Step 1: 書き込みQPS
  平均: 30,000,000 / 86,400 = 347 QPS
  ピーク(x3): 1,041 QPS

  Step 2: 読み取りQPS
  平均: 347 x 200 = 69,400 QPS
  ピーク: 1,041 x 200 = 208,200 QPS

  Step 3: CDN帯域幅
  1回の読み取りで平均 500KB の画像を返すと仮定:
  ピーク読み取り帯域幅:
  208,200 QPS x 500 KB = 104,100,000 KB/s
  = 約 99.3 GB/s = 約 794 Gbps

  Step 4: オリジン帯域幅
  CDNキャッシュヒット率95%:
  オリジンへのリクエスト: 208,200 x 0.05 = 10,410 QPS
  オリジン帯域幅: 10,410 x 500 KB = 約 4.97 GB/s = 約 39.7 Gbps

  インフラ構成の提案:
CDN:
- 全世界に分散配置
- 総帯域幅: 1 Tbps 以上
- キャッシュ容量: 各PoP 数百TB
オリジン:
- 複数リージョン
- 帯域幅: リージョンあたり 50+ Gbps
- S3 + CloudFront 構成
アップロード:
- 直接S3アップロード(署名付きURL)
- 非同期サムネイル生成(Lambda/SQS)
- 帯域幅: ピーク 1,041 x 2MB = 約 16.7 Gbps

13. FAQ

Q1: 「1GBのRAMで何件のレコードが保持できますか?」の見積もり方は?

A: レコードサイズの見積もりが出発点となる。例えばユーザーレコードが ID(8B) + 名前(100B) + メール(100B) + メタデータ(100B) = 約300B/レコードだとすると、1 GiB / 300B = 約360万レコードが理論上格納可能である。ただし、以下のオーバーヘッドを考慮する必要がある。

  • インデックス: レコードサイズの2-3倍のメモリを消費
  • メモリアロケータのフラグメンテーション: 10-30%のオーバーヘッド
  • データ構造のポインタ等: レコードあたり数十バイト
  • ガベージコレクタ(Java/Go等): ヒープの1.5-2倍のメモリが必要

これらを考慮すると、実質的には理論値の1/3〜1/5程度、つまり70万〜120万レコード程度が現実的な見積もりとなる。

Q2: クラウドとオンプレのストレージコスト、どちらが安い?

A: 規模と利用パターンによって異なる。一般的な判断基準は以下の通りである。

  • 数TB以下: クラウドが有利。管理コスト(人件費、設備費、電力費)の削減効果が大きい。
  • 数十TB〜数百TB: ケースバイケース。ワークロードの特性や成長率に依存する。
  • PB規模以上: オンプレが有利な場合が多い。Netflix や Dropbox がオンプレ回帰した事例がある。

ただしオンプレには隠れたコストが存在する。人件費(運用チーム)、データセンターの賃料・電力・冷却、ハードウェアの減価償却(通常3-5年)、ネットワーク回線費用、災害対策設備などを加算すると、単純な$/TB比較とは大きく異なる結果になる場合がある。

Q3: 全てのデータを永遠に保持すべきですか?

A: いいえ。データ保持ポリシー(Data Retention Policy)の策定は、コストとコンプライアンスの両面で不可欠である。推奨される保持期間の目安は以下の通りである。

  • アプリケーションログ: 90日〜1年(障害調査に必要な範囲)
  • アクセスログ: 1〜3年(セキュリティ監査要件に準拠)
  • ユーザーデータ: 退会後一定期間(GDPR では原則消去義務あり)
  • 金融取引データ: 法令により7〜10年の保持義務
  • バックアップ: 世代管理(日次7世代、週次4世代、月次12世代が一般的)
  • メトリクス/監視データ: 高精度は30日、集約データは1-2年

Q4: RAIDレベルによって実効容量はどう変わりますか?

A: RAIDレベルごとの実効容量は以下の通りである。

RAIDレベル別の実効容量(N台のディスク、各C TB):
RAID実効容量冗長性用途
RAID 0N x Cなし一時データ
RAID 1CミラーOS / ブート
RAID 5(N-1) x C1台故障可読み取り中心
RAID 6(N-2) x C2台故障可大容量・高信頼
RAID 10N/2 x Cミラー対DB / 高IOPS
例: 10 TB HDD x 8台の場合
  RAID 0:  80 TB(冗長性なし — 非推奨)
  RAID 1:  10 TB(8台のうち2台のみ使用するのが一般的)
  RAID 5:  70 TB
  RAID 6:  60 TB
  RAID 10: 40 TB

Q5: SSD の容量はなぜ 120GB や 480GB のような中途半端な数字が多いのですか?

A: SSD の NAND チップは2のべき乗(128 GiB, 256 GiB, 512 GiB)の容量で製造される。ここからオーバープロビジョニング(OP)領域を差し引いた上で、10進表記に丸めた値がメーカー表記となる。

例: 128 GiB のNANDチップ

  • OP 7%: 128 GiB x 0.93 = 119 GiB = 約 128 GB → 「120 GB」として販売
  • OP 12%: 128 GiB x 0.88 = 112.6 GiB = 約 121 GB → 上位モデルは「128 GB」

OPは、ウェアレベリング、不良ブロック管理、ガベージコレクション、TRIM処理のために使用される予約領域であり、SSDの寿命と性能を維持するために不可欠である。

Q6: データの圧縮率はどのように見積もればよいですか?

A: データの種類によって圧縮率は大きく異なる。一般的な目安は以下の通りである。

データ種別ごとの圧縮率目安:
データ種別圧縮率備考
プレーンテキスト60-80%gzip/zstd で高圧縮
JSON / XML70-90%冗長性が高く良く縮む
ログファイル80-95%繰り返しパターンが多い
ソースコード60-75%テキストの一種
データベースダンプ70-85%構造的冗長性あり
JPEG / PNG0-5%既に圧縮済み
MP3 / AAC0-3%既に圧縮済み
H.264 / H.2650-2%既に圧縮済み
暗号化データ0%圧縮不可能
ランダムデータ0%エントロピー最大
圧縮率 = (1 - 圧縮後サイズ / 圧縮前サイズ) x 100%

  重要: 既に圧縮されたデータや暗号化データは、
  追加の圧縮でサイズが増加する場合がある。

14. エッジケースと注意点

14.1 ファイルシステムごとのサイズ制限

主要ファイルシステムのサイズ制限:
FS最大ファイルサイズ最大ボリューム備考
FAT324 GiB - 12 TiBUSB等
exFAT16 EiB128 PiBSD/USB
NTFS16 TiB256 TiBWindows
ext416 TiB1 EiBLinux
XFS8 EiB8 EiBLinux
Btrfs16 EiB16 EiBLinux
ZFS16 EiB256 ZiB(理論)各種
APFS8 EiB制限なし(実質)macOS
よくあるトラブル:
  - FAT32 で 4GB 以上のファイルが保存できない
    → 解決: exFAT にフォーマットし直す
  - ext4 のデフォルト inode 数不足(大量の小ファイル)
    → 解決: mkfs 時に -i オプションで inode 密度を調整

14.2 データベースのサイズ見積もり

RDB のストレージ見積もりの考慮事項:

  1. テーブルデータ本体
     行数 x 1行あたりの平均バイト数

  2. インデックス
     B-tree インデックス: テーブルサイズの 20-100%
     カバリングインデックス: さらに大きい
     目安: インデックス合計 = テーブルサイズ x 1.5-3倍

  3. WAL / Redo ログ
     PostgreSQL: wal_size パラメータ(デフォルト 1GB)
     MySQL: innodb_log_file_size x innodb_log_files_in_group

  4. MVCC / バキューム
     PostgreSQL: 更新頻度が高いと dead tuple で膨張
     最大: テーブルサイズの2-5倍に膨張する場合あり

  5. TOAST / LOB
     大きなカラム値は別テーブルに格納される

  計算式の目安:
  必要ストレージ = テーブルデータ
                   x (1 + インデックス倍率)
                   x (1 + MVCC膨張率)
                   x (1 + WAL/一時ファイル)
                   + レプリカ分

  例: 100GB のテーブルデータの場合
  = 100 GB x 2.5(インデックス) x 1.3(MVCC) x 1.1(WAL)
  = 357.5 GB(1ノード分)
  x 3(レプリカ)= 1,072.5 GB = 約 1 TB

FAQ

Q1: このトピックを学ぶ上で最も重要なポイントは何ですか?

実践的な経験を積むことが最も重要です。理論だけでなく、実際にコードを書いて動作を確認することで理解が深まります。

Q2: 初心者がよく陥る間違いは何ですか?

基礎を飛ばして応用に進むことです。このガイドで説明している基本概念をしっかり理解してから、次のステップに進むことをお勧めします。

Q3: 実務ではどのように活用されていますか?

このトピックの知識は、日常的な開発業務で頻繁に活用されます。特にコードレビューやアーキテクチャ設計の際に重要になります。


15. まとめ

15.1 重要概念の整理

概念 ポイント
ビット 情報の最小単位。2状態(0/1)を表す
バイト 8ビット。アドレス指定の最小単位
2進接頭辞 KiB(2^10), MiB(2^20), GiB(2^30) — 1024の累乗
10進接頭辞 KB(10^3), MB(10^6), GB(10^9) — 1000の累乗
テキスト 日本語1文字(UTF-8) = 約3B。新書1冊 = 約300KB
画像 Web写真 = 約100-500KB。RAW = 25-50MB
動画 1080p 1分 = 約25-45MB(コーデック依存)
見積もり DAU x 行動 x データサイズ x レプリカ x 保持期間
コスト RAM: $3000/TB/月 → SSD: $50 → HDD: $5 → テープ: $0.5
帯域幅 ネットワーク = bits/s、ストレージ = bytes。8で割る

15.2 チートシート: 概算のための暗記事項

即座に使える概算値:

  時間:
    1日 = 約 10^5 秒 (86,400)
    1年 = 約 3 x 10^7 秒 (31,536,000)

  2のべき乗:
    2^10 = 約 10^3 (1,024)
    2^20 = 約 10^6 (1,048,576)
    2^30 = 約 10^9 (1,073,741,824)
    2^40 = 約 10^12

  データサイズ:
    英字1文字 = 1 B
    日本語1文字(UTF-8) = 3 B
    画像(Web用) = 100-500 KB
    MP3 1分 = 約 1 MB
    HD動画 1分 = 約 25-45 MB

  帯域幅:
    1 Gbps = 125 MB/s(8で割る)
    オーバーヘッド込みで約 100-110 MB/s

  QPS:
    1M DAU x 1 action/day = 約 12 QPS
    ピーク = 平均 x 2-3

16. 次に読むべきガイド


次に読むべきガイド


参考文献

  1. Shannon, C. E. "A Mathematical Theory of Communication." Bell System Technical Journal, 1948. — 情報理論の基礎を築いた歴史的論文。ビットの概念を定式化。
  2. IEC 60027-2: "Letter symbols to be used in electrical technology — Part 2: Telecommunications and electronics." International Electrotechnical Commission, 1998 (amended 2005). — 2進接頭辞(KiB, MiB, GiB等)を正式に定義した国際規格。
  3. Dean, J. and Barroso, L. A. "The Tail at Scale." Communications of the ACM, Vol. 56, No. 2, 2013. — Google のインフラ設計哲学。レイテンシの数字の出典として広く引用される。
  4. Kleppmann, M. "Designing Data-Intensive Applications." O'Reilly Media, 2017. — データシステムの設計原則を包括的に解説。容量設計の章が特に有用。
  5. Xu, A. "System Design Interview — An Insider's Guide." Byte Code LLC, 2020. — Chapter 2 "Back-of-the-envelope Estimation" が容量見積もりの体系的な方法論を提供。
  6. Patterson, D. A. and Hennessy, J. L. "Computer Organization and Design: The Hardware/Software Interface." 6th Edition, Morgan Kaufmann, 2020. — メモリ階層とストレージ技術の教科書的解説。
  7. AWS Documentation. "Amazon S3 Storage Classes." https://aws.amazon.com/s3/storage-classes/ — クラウドストレージの階層設計における具体的なコストと特性の公式リファレンス。