InnoDBとMyISAMどっちが速いか?の続きです。

人の結果を見ているだけなのもなんなので、自分で試してみました。

計測用ツールはMySQL Performance Blogからダウンロードして、ほぼそのまま利用しました。

計測に使ったサーバはかなり古いものです。

HP DL350
Linux version 2.6.9-5.ELsmp (bhcompile@decompose.build.redhat.com) (gcc version 3.4.3 20041212 (Red Hat 3.4.3-9.EL4)) #1 SMP Wed Jan 5 19:30:39 EST 2005

Intel(R) Pentium(R) III CPU family×2
cpu MHz : 1396.686
cache size : 512 KB
3GB of RAM

OSもMySQLも32bitです。
MySQL Performance Blogでは5.1.14-betaですが、5.1がまだ仕事で使える訳ではないので5.0.37にしています。

同時スレッド数でのパフォーマンスの変化を見てみます。

1.以下のテーブルに、データを100万件登録しました。

SQL:
  1. CREATE TABLE IF NOT EXISTS normal(
  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. ) ENGINE=innoDB;
  16.  
  17. CREATE TABLE IF NOT EXISTS normal2 (
  18. `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  19. `name` varchar(64) NOT NULL DEFAULT '',
  20. `email` varchar(64) NOT NULL DEFAULT '',
  21. `password` varchar(64) NOT NULL DEFAULT '',
  22. `dob` date DEFAULT NULL,
  23. `address` varchar(128) NOT NULL DEFAULT '',
  24. `city` varchar(64) NOT NULL DEFAULT '',
  25. `state_id` tinyint(3) UNSIGNED NOT NULL DEFAULT '0',
  26. `zip` varchar(8) NOT NULL DEFAULT '',
  27. `country_id` smallint(5) UNSIGNED NOT NULL DEFAULT '0',
  28. PRIMARY KEY  (`id`),
  29. UNIQUE KEY `email` (`email`),
  30. KEY `country_id` (`country_id`,`state_id`,`city`)
  31. ) ENGINE=MyISAM;

PRIMARY KEYであるidには1~1000000の値がセットされています。

2.試しに計測したSQLは以下の通りです。

SELECT name FROM normal WHERE id = %d <=== InnoDB
SELECT name FROM normal2 WHERE id = %d <=== MyISAM

%dを1~1000000の範囲でランダムに変化させながら実行します。

PRIMARY KEYによるランダムアクセスの繰り返しです。

3.同時スレッドを1,2,4,8,16,32,64,128と変えながら1秒間のクエリー処理数を計測します。

4.60秒間事前に実行(アイドリング)してから、60秒3回計測してその平均を算出します。

5.MySQLの初期化パラメータは以下の通りです。

[mysqld]
port = 3306
socket = /tmp/mysql.sock
skip-locking

sort_buffer_size = 1M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 64M
thread_cache_size = 64
max_allowed_packet = 16M
key_buffer_size=1250M
innodb_buffer_pool_size=1250M
innodb_log_file_size=10M
innodb_thread_concurrency=8
max_connections=1500
table_cache=1024
net_read_timeout=30
net_write_timeout=30
back_log=128

※クエリーキャッシュを利用すると計測の意味が無くなってしまうので使用していません。

計測中のvmstatの状態はこんな感じです。
ほどんどキャッシュに載っているので、waはほぼゼロ。IO待ちは出ていません。

InnoDBで同時スレッド32の場合のvmstatの状態

CODE:
  1. procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
  2. r  b   swpd   free   buff  cache   si   so    bi    bo   in    cs us sy id wa
  3. 29  0      0 467980  46048 2190212    0    0     0     0 2274 46849 77 23  0  0
  4. 29  0      0 467916  46048 2190212    0    0     0    12 1119 19279 78 22  0  0
  5. 30  0      0 467916  46048 2190212    0    0     0     0 1031 18974 75 25  0  0
  6. 26  0      0 467916  46048 2190212    0    0     0     0 1191 24288 78 22  0  0
  7. 25  0      0 467916  46048 2190212    0    0     0     0 1154 16029 77 23  0  0
  8. 27  0      0 467916  46048 2190212    0    0     0    12 1284 19557 78 22  0  0
  9. 33  0      0 467916  46048 2190212    0    0     0     0 1420 21790 76 24  0  0
  10. 38  0      0 467916  46048 2190212    0    0     0     0 1276 26261 78 22  0  0
  11. 38  0      0 467916  46048 2190212    0    0     0     0 1130 21650 77 23  0  0

MyISAMで同時スレッド32の場合のvmstatの状態

CODE:
  1. procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
  2. r  b   swpd   free   buff  cache   si   so    bi    bo   in    cs us sy id wa
  3. 11  0      0 269836  45824 2190176    0    0     0    16 1228 17138 79 21  0  0
  4. 21  0      0 269836  45824 2190176    0    0     0    20 1156 17048 79 21  0  0
  5. 13  0      0 269836  45824 2190176    0    0     0    20 1272 19751 81 19  0  0
  6. 20  0      0 269836  45824 2190176    0    0     0    16 1063 14680 79 21  0  0
  7. 15  0      0 269836  45824 2190176    0    0     0     0 1105 15855 79 21  0  0
  8. 13  0      0 269836  45824 2190176    0    0     0    20 1631 24111 79 21  0  0
  9. 2  0      0 269836  45824 2190176    0    0     0    16 1043 15785 80 20  0  0
  10. 26  0      0 269836  45824 2190176    0    0     0    28 1117 15955 79 21  0  0

結果はこうなりました。

スレッド数 MyISAM InnoDB

PrimaryKeyによるランダムアクセスの計測結果


MySQL Performance Blogの結果とはずれています。
ピーク時の同時スレッド数が低いのはCPUの処理能力が低いせいだと思いますが、
スレッド数を上げていった時にMyISAMの処理性能が落ちないことが妙な感じです。
特に128同時スレッドで急に値が上昇しています。
MySQL Performance Blogの計測ではInnoDBと同じ傾向で性能が落ちていったのですが。

MySQL Performance Blogの計測では
sort_buffer_size、read_buffer_size、read_rnd_buffer_size、myisam_sort_buffer_size
を指定していないので初期値が採用されることが理由でしょうか。

普通に考えて、関係あるのはread_rnd_buffer_sizeくらいかと思えます。
でも、同時処理性能とは直接関係するとも思えないのですが・・・・・。

次回はこのあたりを探ってみます。続きます