MariaDBのInnoDBとZFSの書き込み単位

MariDBのパフォーマンス改善の資料を読んで、AIと会話しているときに「ZFSのrecordsizeをInnoDBと合わせるといい」という提案を受けたときの覚書。
Gemini 3 Flash Previewと会話。
参考サイト:Optimization and Tuning | Server | MariaDB Documentation

環境: FreeBSD 14.3-RELEASE-p10, MariaDB Server 11.8.6


1. ZFSとInnoDBの書き込み単位

  • InnoDB Page Size(MariaDB側):InnoDBがデータを管理・ディスクへ読み書きする最小単位。デフォルトは 16KB。
    データベースはこの16KBの「ページ」という箱の中に、実際のレコード(行)を詰め込んで管理する。
  • ZFS recordsize(ファイルシステム側):ZFSがディスクに書き込む際の最大ブロックサイズ。デフォルトは 128KB 。

不一致が起きると
128KBの枠(ZFS)の中に、16KBのデータ(InnoDB)を書き込もうとすると、ZFSは
「隙間を埋めるために残りの112KBを一旦読み込み、16KBを混ぜて、再度128KBとして書き直す」
というRead-Modify-Write (RMW) という無駄な動作を強制される。


ZFSのrecordsizeを確認。
# zfs get recordsize,atime,compression /var/db/mysql

NAME                PROPERTY     VALUE           SOURCE
zroot/ROOT/default  recordsize   128K            default
zroot/ROOT/default  atime        off             inherited from zroot
zroot/ROOT/default  compression  lz4             inherited from zroot


InnoDBの書き込み単位を確認。
# mariadb -e "SHOW VARIABLES LIKE 'innodb_page_size';"

+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+


書き込み単位を合わせる技術的メリット

  • Read-Modify-Writeの回避:
    前述の通り、無駄な「読み込み→合成→書き込み」がなくなるため、ディスクI/Oの回数が激減する。
  • Write Amplification(書き込み増幅)の抑制:
    16KBの変更のために128KBを書き込むという「8倍の無駄」がなくなる。
    これによりSSDの寿命が延びスループットが向上。
  • ARC(ZFSキャッシュ)の効率化:
    ZFSのメモリキャッシュ(ARC)が16KB単位で管理されるようになり、MariaDBのBuffer Poolと単位が揃うため、メモリの利用効率が最適化される。
  • 断片化の防止:
    ブロックサイズが揃うことで、長期間運用した際のデータの断片化(フラグメンテーション)が抑えられる。


デメリット

ZFSのプロパティ(recordsizeなど)は、データセット単位でしか設定できない。
そのためDB専用のデータセットを作成し、そこに専用のプロパティ(recordsize=16k, atime=offなど)を設定する必要がある。

atime: 「ファイルに最後にアクセス(読み取り)した時刻」を記録する機能。


次回サーバー移行時にやってみる予定。


2.  InnoDBの内部情報とパフォーマンス測定

InnoDBのメモリ(バッファプール)のヒット率を取得。
# mariadb -e "SHOW ENGINE INNODB STATUS\G" | grep "Buffer pool hit rate"

Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000

ヒット率100%。
過去1000回のデータ読み取りリクエストのうち、1000回がメモリ上で完結した(ディスクまで取りに行かずに済んだ)。


パフォーマンス測定。
# mariadb-slap --user=root --password --auto-generate-sql --concurrency=10 --iterations=5 --number-int-cols=5 --number-char-cols=20 --engine=innodb

オプションの意味

  • --auto-generate-sql: テスト用のテーブルとデータを自動で作成。テストが終わると自動で削除。本番のデータには一切触れない。
  • --concurrency=10: 同時接続数。10人のユーザーが同時に激しくクエリを投げている状態をシミュレート。
  • --iterations=5: テストを5回繰り返す。1回だけだと誤差が出るため、複数回実施して平均をとる。
  • --number-int-cols=5 / --number-char-cols=20: 作成するテストテーブルの構成を指定(数値型5列、文字型20列)。
  • --engine=innodb: InnoDBエンジンを使用してテストすることを指定。



▼ 関連記事