MySQLパフォーマンスBlog

InnoDB vs MyISAM vs Falcon benchmarks

というエントリィがあったのでチェック?してみました。

検証環境は
-----------------------------------------

CentOS release 4.4 (Final)
2 х Dual Core Intel XEON 5130
model name : Intel(R) Xeon(R) CPU 5130 @ 2.00GHz
stepping : 6
cpu MHz : 1995.004
cache size : 4096 KB
16GB of RAM

MySQL version
MySQL 5.1.14-beta sources for MyISAM / InnoDB
MySQL 5.1.14-falcon bitkeeper tree
bk://mysql.bkbits.net/mysql-5.1-falcon for Falcon

MyISAM / InnoDB:
libexec/mysqld --no-defaults
--user=root
--key-buffer-size=1500M
--innodb-buffer-pool-size=1500M
--innodb-log-file-size=100M
--innodb-thread-concurrency=8
--max-connections=1500
--table-cache=512
--net_read_timeout=30
--net_write_timeout=30
--back_log=128

-----------------------------------------

ということで、InnoDB vs MyISAM vs Falcon のベンチマークをした結果だそうです。

FalconはMySQLのストレージエンジンで、Jim Starkey氏と、彼の妻であるAnn Harrison氏を中心に開発が進められている
とのことですが詳しくはこちらをどうぞ。

仕事レベルでFalconが使えるようになるのは、ずいぶん先の話なのでとりあえず、InnoDB vs MyISAM に着目して読んでみました。

ベンチマークの方法としては:
1. 100万件データがあるテーブルを用意した(全部で350MB)
2. 1, 4, 16, 64, 128, 256 同時スレッドでそれぞれ試した
3. 1)180秒事前にSQLを流して
2)60秒間計測した
3)3回流して一番良い結果のものを採用した
とのことです。

テーブル内容は以下の通り

SQL:
  1. CREATE TABLE IF NOT EXISTS `$tableName` (
  2. `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `name` varchar(64) NOT NULL DEFAULT '',
  4. `email` varchar(64) NOT NULL DEFAULT '',
  5. `password` varchar(64) NOT NULL DEFAULT '',
  6. `dob` date DEFAULT NULL,
  7. `address` varchar(128) NOT NULL DEFAULT '',
  8. `city` varchar(64) NOT NULL DEFAULT '',
  9. `state_id` tinyint(3) UNSIGNED NOT NULL DEFAULT '0',
  10. `zip` varchar(8) NOT NULL DEFAULT '',
  11. `country_id` smallint(5) UNSIGNED NOT NULL DEFAULT '0',
  12. PRIMARY KEY  (`id`),
  13. UNIQUE KEY `email` (`email`),
  14. KEY `country_id` (`country_id`,`state_id`,`city`)
  15. )

READ_PK_POINT(PRIMARY KEY指定)

SQL:SELECT name FROM $tableName WHERE id = %d
PRIMARY KEYでアクセス
取得するデータはPRIMARY KEY以外

傾向 InnoDBとMyISAMはほぼ同様の性能
同時4スレッドが一番性能が良くて
InnoDB:45000querles/秒くらい
MyISAM:42000querles/秒くらい
6-9%くらいInnoDBが速い

READ_KEY_POINT(INDEX指定)

SQL:SELECT name FROM $tableName WHERE country_id = %d
複合INDEXの先頭項目でアクセス
取得するデータはINDEX以外
取得件数が不明(たぶんかなりの件数取得しているはず)
※UNIQUE KEYも試してほしかった・・・・

傾向 InnoDBの勝ち
同時4~16スレッドが一番性能が良くて
InnoDB:110querles/秒くらい
MyISAM: 85querles/秒くらい
30%くらいInnoDBが速い
128スレッド以上でMyISAMの性能が極端に落ちている
ブログの作者が
There MyISAM shows bad scalability with increasing count of thread.
I think the reason is pread systemcall MyISAM uses to access data
and retrieving from OS cache is not scaled.
とコメントしている。

READ_KEY_POINT_LIMIT

SQL:SELECT name FROM $tableName WHERE country_id = %d LIMIT 5
複合INDEXの先頭項目でアクセス
limitで先頭5件だけ
取得するデータはINDEX以外

傾向 InnoDBの勝ち
同時4~16スレッドが一番性能が良くて
InnoDB:25000querles/秒くらい
MyISAM:16000querles/秒くらい
58%くらいInnoDBが速い
16スレッド以上でInnoDBの性能が徐々に落ちている
ブログの作者が
Perhaps there is still a problem with InnoDB mutexes.
とコメントしている。

READ_KEY_POINT_NO_DATA

SQL:SELECT state_id FROM $tableName WHERE country_id = %d
複合INDEXの先頭項目でアクセス
取得するデータは複合INDEXに含まれている

傾向 InnoDBの勝ち
同時4~128スレッドが一番性能が良くて
InnoDB:195querles/秒くらい
MyISAM:150querles/秒くらい
25-30%くらいInnoDBが速い
スレッド数を増やしても性能は落ちない

READ_KEY_POINT_NO_DATA_LIMIT

SQL:SELECT state_id FROM $tableName WHERE country_id = %d LIMIT 5
複合INDEXの先頭項目でアクセス
limitで先頭5件だけ
取得するデータは複合INDEXに含まれている

傾向 InnoDBの勝ち
同時4~64スレッドが一番性能が良くて
InnoDB:31000querles/秒くらい
MyISAM:17000querles/秒くらい
87% くらいInnoDBが速い
InnoDBは128スレッド以上で性能が極端に低下

READ_PK_POINT_INDEX

SQL:SELECT id FROM $tableName WHERE id = %d
PRIMARY KEYでアクセス
取得するデータはPRIMARY KEY項目のみ

傾向 InnoDBとMyISAMはほぼ同様の性能
同時4~64スレッドが一番性能が良くて
InnoDB:45500querles/秒くらい
MyISAM:44500querles/秒くらい
数%InnoDBが速い

READ_PK_RANGE

SQL:SELECT min(dob) FROM $tableName WHERE id between %d and %d
PRIMARY KEYで範囲指定
取得するデータはPRIMARY KEY以外でminを取得している

傾向 InnoDBの勝ち
同時4~16スレッドが一番性能が良くて
InnoDB:20000querles/秒くらい
MyISAM: 6000querles/秒くらい
InnoDBが2~26倍速い
MyISAMは64スレッド以上で性能が極端に低下

READ_PK_RANGE_INDEX

SQL:SELECT count(id) FROM $tableName WHERE id between %d and %d
PRIMARY KEYで範囲指定
取得するデータはPRIMARY KEY項目のみでcountを取得している

傾向 InnoDBの勝ち
同時4~16スレッドが一番性能が良くて
InnoDB:22000querles/秒くらい
MyISAM:16000querles/秒くらい
InnoDBが37%速い
MyISAMがスレッド数が増えても性能が落ちない
ブログの作者が
MyISAM scales good here, because of access only to key column and 'pread' syscall is not used.
とコメントしている。

READ_KEY_RANGE

SQL:SELECT name FROM $tableName WHERE country_id = %d and state_id between %d and %d
複合INDEXの先頭項目の完全一致+2番目の項目の範囲指定でアクセス
取得するデータはKEY項目以外

傾向 InnoDBとMyISAMはほぼ同様の性能
同時4~64スレッドが一番性能が良くて
InnoDB:440querles/秒くらい
MyISAM:410querles/秒くらい
InnoDBが7%くらい速い
MyISAMは128スレッド以上で性能が極端に低下

READ_KEY_RANGE_LIMIT

SQL:SELECT name FROM $tableName WHERE country_id = %d and state_id between %d and %d LIMIT 50
複合INDEXの先頭項目の完全一致+2番目の項目の範囲指定でアクセス
limitで先頭50件だけ
取得するデータはKEY項目以外

傾向 InnoDBの勝ち
同時4スレッドが一番性能が良くて
InnoDB:7400querles/秒くらい
MyISAM:6000querles/秒くらい
InnoDBが23%くらい速い
MyISAMは256スレッド以上で性能が極端に低下
InnoDBも16スレッド数以上で徐々に性能低下

READ_KEY_RANGE_NO_DATA

SQL:SELECT city FROM $tableName WHERE country_id = %d and state_id between %d and %d
複合INDEXの先頭項目の完全一致+2番目の項目の範囲指定でアクセス
取得するデータは複合INDEXの3番目の項目

傾向 InnoDBの勝ち
同時4~16スレッドが一番性能が良くて
InnoDB:900querles/秒くらい
MyISAM:700querles/秒くらい
InnoDBが28%くらい速い
MyISAM、InnoDBともにスレッド数を上げても性能低下が少ない

READ_KEY_RANGE_NO_DATA_LIMIT

SQL:SELECT city FROM $tableName WHERE country_id = %d and state_id between %d and %d LIMIT 50
複合INDEXの先頭項目の完全一致+2番目の項目の範囲指定でアクセス
取得するデータは複合INDEXの3番目の項目
limitで先頭50件だけ

傾向 InnoDBの勝ち
同時4~16スレッドが一番性能が良くて
InnoDB:900querles/秒くらい
MyISAM:700querles/秒くらい
InnoDBが28%くらい速い
MyISAM、InnoDBともにスレッド数を上げても性能低下が少ない

READ_FTS

SQL:SELECT min(dob) FROM $tableName
FullScan
minを取っている

傾向 InnoDBとMyISAMはほぼ同様の性能
スレッド数を上げても性能低下がない
InnoDB:5.5querles/秒くらい
MyISAM:4~6querles/秒くらい
4~16スレッドの場合InnoDBが20%くらい速い
MyISAM、InnoDBともにスレッド数を上げても性能低下がない

他の検証例を少しだけ探してみたのですがあまり見つかりませんでした

徹底比較!! MySQLエンジン:第6回:ストレージエンジンの処理性能比較
があったので比較してみます。MySQL 5.0.22での検証です。

設定は
>OSには「CentOS 4.2」を使用しました。MySQLはソースからインストールし、「my-large.cnf」を変更しないで
>使用しました。よって、MySQLのInnoDBエンジンが使用するデータベース・バッファのサイズは256MBになります。
だそうです。

こちらの結果を見てみると
1)SELECT COUNT(*) FROM TEST00
MyISAMが圧倒的に速い
2)SELECT SUM(ADDR_CO_ID) FROM TEST00
MyISAMとInnoDBがほぼ同等の性能
3)SELECT ADDR_CO_ID FROM TEST00 WHERE ADDR_ID = ? (ADDR_IDはPKEY)
MyISAMとInnoDBがほぼ同等の性能
となっています。

この結果とInnoDB vs MyISAM vs Falcon benchmarksを考えてみると
1)SELECT COUNT(*) FROM TEST00
InnoDB vs MyISAM vs Falcon benchmarks に該当するものがない
2)SELECT SUM(ADDR_CO_ID) FROM TEST00
InnoDB vs MyISAM vs Falcon benchmarks はinnodb_buffer_pool_sizeに1500M指定している
ことを考慮すると、理解可能な気がします。
3)SELECT ADDR_CO_ID FROM TEST00 WHERE ADDR_ID = ? (ADDR_IDはPKEY)
InnoDB vs MyISAM vs Falcon benchmarks とほぼ同様の結果
ということで矛盾はしないかなと思います。

とりあえず続きます