こんにちは。不可思議絵の具です。
WordPressのデータベースには「MySQLデータベースシステム」(又はMariaDB。以後MySQLで統一)が用いられており、実際にデータを管理する処理部である「ストレージエンジン」に『MyISAM』と『InnoDB』を選択できます。
では、この2つの違いって何でしょうか?
どちらのほうがWordPressに向いているのでしょうか?
結論から言うと、一般的な InnoDBで間違いがない。
様々なサイトを参照して、私なりに結論を出しました。
ストレージエンジンとは?
ストレージエンジンとはデータを実際に読み書きする処理を担当する部分で、「MyISAM」と「InnoDB」が特に良く利用されます。
MySQL 5.5未満は「MyISAM」が標準でしたが、5.5以降は「InnoDB」が標準です。
WordPressはインストール時にデータベースに設定された標準のストレージエンジンをそのまま使いますので、
- MySQL 5.5未満と組み合わせたWordPressのテーブルは全てMyISAM
- MySQL 5.5以降と組み合わせたWordPressのテーブルは全てInnoDB
という状態でセットアップされます。
そのため、昔から作ってあるブログは「MyISAM」で構成されていることが殆どです。
MyISAMとInnoDBの機能差
「標準になるくらいだから、InnoDBの方が良いモノなんでしょ?」
おっしゃる通りで、InnoDBはMyISAMに較べて高機能です。
大きな違いを上げてゆきます。
ロックの粒度が細かい
MyISAMはテーブル単位ロック、InnoDBは行単位ロックです。
MyISAM の場合 | 誰かがテーブルを更新している最中は、 他の人は参照できない |
---|---|
InnoDB の場合 | 誰かがテーブルを更新している最中でも、 他の人は更新対象行以外は参照できる |
という動きの違いになります。
WordPressというアプリケーションレベルでの動作というと、
MyISAM の場合 | 記事登録ボタンを押した数秒間、 訪問者は白い画面で待たされる |
---|---|
InnoDB の場合 | 記事登録ボタンを押した数秒間、 訪問者は待たされずに他の記事を読める |
という動きになります。
訪問者が多いサイトではこのUX面の差は大きいでしょう。
MVCCがある
InnoDBにはMVCC(マルチ・バージョン・コンカレンシ・コントロール)が付いています。
細かい説明は省きますが、更新により行ロック中の行を参照する状況になっても、更新前のバージョンを参照することでロック解除待ちが不要になります。
銀行のオンラインシステムと違い、更新前の記事が表に出てしまっても何ら困らない使い道であることが前提です。
要するに、InnoDBは元々行ロックで影響範囲が少ない上、その行についてもMVCCのお陰で更新中も参照できるので、待ちが全く発生しないということです。
行ロック同様、訪問者が多いサイトでは効果が大きいでしょう。
クラスタインデックスになっている
InnoDBではクラスタインデックスが使われます。
クラスタインデックスでは、インデックスに主キーとデータがセットで格納されているので、主キーのインデックスが効くと抽出が非常に高速になる特徴があります。
(インデックスがマッチした時にはデータの読み取りも完了しているため)
残念ながらWordPressは主キーがビシっと当たるテーブルレイアウトではないので(セカンダリーインデックス頼み)、用途に凄くマッチしているという訳ではありません。
トランザクションがある
MyISAMにはトランザクションがありませんが、InnoDBにはトランザクションがあります。
WordPressがMyISAMでも使えるってことは、トランザクションのロジックを自力実装しているということになりますので、直接のメリットではありません。
しかし、WordPress上で動くアプリケーション(掲示板、在庫管理、アンケート…etc.)を追加開発する場合は重要な機能です。
MyISAMよりInnoDBの方が壊れにくい
トランザクション機能の関係で構造が根本から違うからだと思いますが、MyISAMの方がディスク異常やサーバーの異常停止などのトラブルに弱く、壊れやすいそうです。
(具体的な根拠を示せず申し訳ないです。すみません)
InnoDBの方が壊れにくいというのは、私としてはこれが一番の利点だと思っています。
よほど速度にこだわらない限りInnoDBで問題ない
ぶっちゃけ、WordPressの利用形態として、
- 更新処理といえば記事の追加・修正くらい
- 更新の頻度は少なく
- ほとんどの場合、管理人が1人で作業する
(だからトランザクション周りで変なことになりにくい)
こういった利用状況がほとんどでしょうから、InnoDBの行ロックやMVCCはそれほど有効では無いかと思います。
InnoDBはメモリ(バッファープール)とCPUを確保できれば性能が向上しますが、共用レンタルサーバーなどのプアな環境では高機能故の過負荷の方がメリットを上回るでしょう。
ですから、
- 日次バックアップ等、トラブル対策を取った上で速度番長と割り切る
- 共用レンタルサーバーで十分なメモリが確保できない
こういった場合は、MyISAMが良いと思います。
それでも、人気記事カウンター(WordPress Popular Posts)やアクセス解析などの更新が頻繁なテーブルについてはInnoDBにしておいた方が良いと思います。
ただ、MySQLのバージョンアップとともにMyISAMとInnoDBの性能差は埋まってきており、InnoDBでもメモリを十分に確保できれば参照系ではほぼ同等のようです。
データの安全を考えると多少の処理速度低下は目をつぶってInnoDBを使ったほうが良い、というのが私なりの見解です。
特にクラウドやVPSなど、メモリを十分に使える環境ではInnoDB一択だと思います。
ストレージエンジンの変更方法
簡単に紹介します。
ALTER TABLE
作成済みのテーブルの場合はALTER TABLE文を実行します。
ALTER TABLE 【テーブル名】 ENGINE = InnoDB;
WordPressの場合、こうです。
ALTER TABLE wp_commentmeta ENGINE = InnoDB;
ALTER TABLE wp_comments ENGINE = InnoDB;
ALTER TABLE wp_links ENGINE = InnoDB;
ALTER TABLE wp_options ENGINE = InnoDB;
ALTER TABLE wp_postmeta ENGINE = InnoDB;
ALTER TABLE wp_posts ENGINE = InnoDB;
ALTER TABLE wp_termmeta ENGINE = InnoDB;
ALTER TABLE wp_terms ENGINE = InnoDB;
ALTER TABLE wp_term_relationships ENGINE = InnoDB;
ALTER TABLE wp_term_taxonomy ENGINE = InnoDB;
ALTER TABLE wp_usermeta ENGINE = InnoDB;
ALTER TABLE wp_users ENGINE = InnoDB;
CREATE TABLE
これから作成するテーブルの場合はCREATE TABLE文にオプションを付加します。
(MySQL 5.5以降は指定しなくてもInnoDBで作られます)
CREATE TABLE 【テーブル名】(列定義) ENGINE = InnoDB;
まとめ
- MySQLのストレージエンジンにはMyISAMとInnoDBがある
- MyISAMの動作は軽いが、更新機能が弱く、データベースが壊れやすい
- InnoDBの動作はMyISAMに比べると少し重いが、MySQLの改善でその差は縮まってきている
- InnoDBには行ロックやMVCCなど、並列性を高める機能がある。
また、データベースの対障害性も高い
よって、WordPressにおいてはどちらを選ぶかというと・・・
- 共用サーバーなどプアな環境では今まで通りMyISAMで良いだろう
- VPSなどリッチな環境ではInnoDBにしない理由はない
という結論になりました。
では(^O^)/
参考資料
- Chapter 15 Alternative Storage Engines (MySQL 5.5マニュアル)
- データベース構造 (WordPress Codex)
- 漢(オトコ)のコンピュータ道
- MySQL with InnoDB のインデックスの基礎知識とありがちな間違い (クックパッド開発者ブログ)
- 運用視点なMyISAMとInnoDBと。 (LexTech)
- MySQL InnoDBストレージエンジンのチューニング(前編) (EnterpriseZine)
- [MySQL] InnoDBを積極的に使わないケース (Qiita)