InnoDB vs MyISAMシリーズがまだ続いています。
前回までで環境や初期化パラメータの設定が落ち着いたので
本格的にInnoDBとMyISAMのパフォーマンスを比較してみます。
測定環境についてはこちらを参照して下さい。
・データ件数は100万件
・こちらの構造のテーブルをInnoDBとMyISAMで作成して処理速度を比較
以下SQL中の「テーブル名 normal」にはMyISAMなら normal2 がセットされます。
1.PrimaryKeyで一件検索
SELECT name FROM normal WHERE id = %d
※%dは1~100万でランダムに変化
※取得カラムはPK以外
| スレッド数 | MyISAM | InnoDB |
前回も書いた通りほぼ「同点」です。
それにしても同時スレッドを上げるときれいに性能が落ちていきます。
2.UniqueIndexで一件検索
SELECT name FROM normal WHERE email = %s
※%sはランダムに変化
※取得カラムはINDEX以外
| スレッド数 | MyISAM | InnoDB |
これもほぼ「同点」と言ってよいと思います。
しかしPrimaryKeyに比べると55%程度の処理しか出来ません。
InnoDBの場合は、PrimaryKeyがクラスターインデックスなので理解できます。
クラスターインデックスであるPrimaryKeyの場合は、PrimaryKeyを取得すると同時にデータページも読み込まれるのですが、通常のINDEXの場合は
1)INDEXを取得
2)INDEXとセットで格納されているPrimaryKeyによってデータを取得
の経路になるため、その分がオーバヘッドになっているはずです。
でもMyISAMの場合は、PrimaryKeyでもINDEXでもOSのIOによってデータページを読み込むはずなのですから、あまり差がないはずなのですが。
別の機会に調べたいと思います。
3.PrimaryKeyで範囲検索
SELECT name FROM normal WHERE id between %d1 and %d2
※(%d1は1~100万でランダムに変化 %d2は%d1+20)
※常に20件取得される
※取得カラムはINDEX以外
| スレッド数 | MyISAM | InnoDB |
70~80%ほどInnoDBが高速になっています。
これもInnoDBのPrimaryKeyがクラスターインデックスであるためでしょうか。
つまり、PrimaryKeyを読み込む際に、キーの値が近いものが隣接しているので、同時にデータページに読み込む確率が高いため。
なんか都合の良い解釈でしょうか?
4.非UniqueIndexで範囲検索
SELECT name FROM $tableName WHERE country_id = %d and state_id between %d1 and %d2
※%dは1~200,%d1は1~50,%d2は%d1に1を足したもの
※取得カラムはINDEX以外
※country_idは1~200、state_idは1~50の範囲なので、country_id+state_idで同じ値は100件づつ存在する。%d2は%d1に1を足したものなので200件づつ取得する。
| スレッド数 | MyISAM | InnoDB |
これはほぼ同点です。
ただPrimaryKeyで1件取得する場合に比べて、スレッド数を上げたときの性能低下の度合いが緩やかです。
特にMyISAMはあまり性能劣化しません。
今後、考えたいと思います。
5.非UniqueIndexで範囲検索 ソートなしで先頭5件を取得
SELECT name FROM normal WHERE country_id = %d LIMIT 5
※%dは1~200でランダム
※取得カラムはINDEX以外
※country_idは1~200の範囲なので、country_idで同じ値は5000件づつ存在する。その先頭5件を取得する。ただし取得時のソートなし。
| スレッド数 | MyISAM | InnoDB |
これもほぼ同点です。
ただ性能劣化の度合いが、「PrimaryKeyで1件取得」と「非UniqueIndexで範囲検索」の中間くらいですね。
まだまだ続きます。









