InnoDB Page Compression: MySQLの容量を50%削減しSSDの寿命を延ばす秘策

MySQL tutorial - IT technology blog
MySQL tutorial - IT technology blog

午前2時のストレージ容量不足という悪夢

深夜にディスク使用率が90%に達したというアラート。これはDBAにとって、決して珍しくない「悪夢」でしょう。大規模なシステムにおいて、データの肥大化はAWS EBSやGoogle Cloud Storageの請求額を増大させるだけではありません。高い書き込み強度(Write IOPS)によって、SSDを物理的に摩耗させる直接的な原因にもなります。

私はかつて、あるECサイトのログシステムを管理していました。当時のorder_historiesテーブルは2億行を超え、150GB以上の容量を占有していました。ストレージの増設を繰り返すのは、その場しのぎの解決策に過ぎませんでした。しかし、InnoDB Page Compressionを導入したところ、容量は70GB以下にまで減少しました。さらに驚くべきことに、クエリのパフォーマンスはほとんど変わりませんでした。

圧縮方式を混同しないでください

設定を始める前に、適切なツールを選択するために、InnoDBにおける2つの圧縮メカニズムを明確に区別しておく必要があります。

1. InnoDB Row Compression(従来の方法)

MySQL 5.5から導入されたこのメカニズムは、行レベルでデータを圧縮し、固定サイズ(例:8KB)のページに詰め込みます。

  • 弱点: Buffer Poolにロードする際に頻繁に解凍が必要なため、CPUに非常に大きな負荷がかかります。また、B-tree内で「ノード分割(node splitting)」が発生しやすく、深刻なインデックスの断片化を引き起こすことがよくあります。

2. InnoDB Page Compression(透過的圧縮)

これは、OSやファイルシステム(EXT4やXFSなど)のSparse Files(スパースファイル)機能を利用した最新のソリューションです。

  • 利点: MySQLは16KBのページを約6〜7KBに圧縮します。余ったスペースはpunch holeコマンドによって解放されます。
  • 実質的なメリット: SSDには実際に圧縮されたデータのみが書き込まれます。これにより、書き込み増幅(Write Amplification)が大幅に削減され、ストレージをより長持ちさせることができます。

なぜ今すぐPage Compressionを有効にすべきなのか?

logstransactionsテーブルが1,000万行を超えると、I/Oボトルネックは避けられません。Page Compressionはこの問題を非常にスマートに解決します。

  1. コスト削減: ディスク容量を40%〜60%節約することで、高価なストレージの追加購入を遅らせることができます。
  2. I/O速度の最適化: データが小さくなるということは、MySQLがディスクからRAMに読み込むバイト数が減ることを意味します。大規模なSELECT文の実行速度が明らかに向上します。
  3. ハードウェアの保護: SSDには総書き込み容量(TBW)の制限があります。データを圧縮して物理的な書き込み頻度を減らすことで、デバイスの寿命を延ばせます。

安全に導入するための要件

この機能はすべてのシステムに適しているわけではありません。以下の技術基準を満たしていることを確認してください。

  • OS: Linuxカーネル バージョン3.10以上。
  • ファイルシステム: 「hole punching」をサポートしていること。最新のUbuntuやCentOSにおけるXFSまたは**EXT4**の使用を推奨します。
  • バージョン: MySQL 5.7.8+ または MariaDB 10.1+。
  • 設定: innodb_file_per_table変数がONであること。

詳細な設定手順

お使いのMySQLサーバーで以下の手順を実行してください。

ステップ1:環境の確認

まず、MySQLが各テーブルを個別のファイルとして保存しているか確認します。

SHOW VARIABLES LIKE 'innodb_file_per_table';

結果がONであれば、準備完了です。

ステップ2:圧縮アルゴリズムを指定して新しいテーブルを作成する

テーブル作成時にCOMPRESSION="zlib"属性を追加するだけです。実務上の経験から、zlibは非常に優れた圧縮率を提供し、一方lz4は処理速度を優先する場合に適しています。

CREATE TABLE logs_thanh_toan (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    content TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB COMPRESSION="zlib";

ステップ3:既存のテーブルを圧縮する

稼働中の巨大なテーブルにはALTER TABLEを使用します。注意点として、このプロセスではテーブル全体の再構築(rebuild)が行われます。システムへの負荷を避けるため、オフピーク時に実行することをお勧めします。

-- 圧縮モードを有効化
ALTER TABLE logs_thanh_toan COMPRESSION="zlib";

-- ディスク上の物理的な空き容量を解放
OPTIMIZE TABLE logs_thanh_toan;

実際の容量を確認する方法

ここが最も間違いやすいポイントです。ls -lhコマンドを使用すると、Linuxは論理サイズ(以前と同じ数値)を表示します。「穴あけ」(punch hole)後の実際の容量を確認するには、duコマンドを使用する必要があります。

# 論理サイズと実際のサイズを比較
du -h --apparent-size /var/lib/mysql/db_name/logs_thanh_toan.ibd
du -h /var/lib/mysql/db_name/logs_thanh_toan.ibd

上記2つのコマンドの結果の差が、あなたが会社のために節約したコストに相当します。

実戦から学んだ「痛い目を見ないための」注意点

Page Compressionは大きなメリットをもたらしますが、注意すべきトレードオフもあります。

  • CPUコスト: 圧縮・解凍処理により、CPUリソースをさらに5〜10%ほど消費します。サーバーのCPU使用率が常に80%を超えている場合は、慎重に検討してください。
  • バックアップの問題: mysqldumpなどのツールは、非圧縮のデータを出力します。Percona XtraBackupを使用する場合は、リストア時にも圧縮状態を維持できるよう、そのバージョンがsparse filesをサポートしているか確認してください。
  • データの種類: 画像、zipファイル、暗号化されたデータが含まれるテーブルを圧縮しても意味がありません。Page Compressionは、テキストデータ、JSON、または重複値の多いログテーブルで最も効果を発揮します。

データベースの最適化はSQLのチューニングだけではありません。データがディスク上にどのように配置されているかを理解することで、システムをより堅牢にし、インフラコストを大幅に削減することができます。

Share: