MySQLブログ | システム監視・サーバ監視・障害監視・ネットワーク監視・システム運用・MySQL・Web地図を提供

MySQLブログ エントリ一覧

今度はブログ系のテーブル構成になっています。

サーバ環境

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は5.0.37。

1.テーブルの構造

1.1 InnoDBのテーブル
SQL:

  1. CREATE TABLE IF NOT EXISTS entry (
  2.     `id`                         int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3.     `status`                     NUMERIC(5)    NOT NULL,
  4.     `category_id`                NUMERIC(10)   NOT NULL,
  5.     `user_type`                  NUMERIC(10)   NOT NULL,
  6.     `name`                       VARCHAR(64)   NOT NULL,
  7.     `favorites`                  NUMERIC(10)   NOT NULL,
  8.     `comments`                   NUMERIC(10)   NOT NULL,
  9.     `trackbacks`                 NUMERIC(10)   NOT NULL,
  10.     `comment_permission`         NUMERIC(10)   NOT NULL,
  11.     `trackback_permission`       NUMERIC(10)   NOT NULL,
  12.     `edited`                     DATETIME      NOT NULL,
  13.     `image`                      NUMERIC(10)   NULL,
  14.     `caption`                    VARCHAR(128)  NULL,
  15.     `user_name`                  VARCHAR(64)   NOT NULL,
  16.     `created`                    DATETIME      NOT NULL,
  17.     `modified`                   DATETIME      NOT NULL,
  18.     `removed`                    DATETIME      NULL,
  19.     `title`                      VARCHAR(1000) NOT NULL,
  20.     `body`                       TEXT          NULL,
  21.     `comment_captcha_permission` NUMERIC(10)   NOT NULL DEFAULT 1,
  22.     `favorite_permission`        NUMERIC(10)   NOT NULL DEFAULT 1,
  23.     PRIMARY KEY  (`id`),
  24.     UNIQUE INDEX `entry_unique` (`name`, `user_name`),
  25.     INDEX `entry_idx1` (`user_name`,`status`,`edited`),
  26.     INDEX `entry_idx2` (`name`,`user_name`,`removed`),
  27.     INDEX `entry_idx3` (`edited`),
  28.     INDEX `entry_idx4` (`trackbacks`,`edited`),
  29.     INDEX `entry_idx5` (`comments`,`edited`),
  30.     INDEX `entry_idx6` (`favorites`,`edited`),
  31.     INDEX `entry_idx7` (`category_id`,`edited`),
  32.     INDEX `entry_idx8` (`created`)
  33.     )” ENGINE=innoDB;
  34. CREATE TABLE IF NOT EXISTS entry_comment (
  35.     `id`                         int(10) unsigned NOT NULL auto_increment,
  36.     `guest_name`                 VARCHAR(300)  null,
  37.     `entry_id`                   NUMERIC(10)   not null,
  38.     `user_name`                  VARCHAR(64)   null,
  39.     `created`                    DATETIME      not null,
  40.     `removed`                    DATETIME      null,
  41.     `body`                       TEXT          null,
  42.     `guest_url`                  VARCHAR(1000) null,
  43.     PRIMARY KEY  (`id`),
  44.     INDEX `entry_comment_idx1` (`entry_id`,`created`,`removed`),
  45.     INDEX `entry_comment_idx2` (`user_name`,`removed`),
  46.     INDEX `entry_comment_idx3` (`removed`,`created`),
  47.     INDEX `entry_comment_idx4` (`user_name`)
  48.     )”  ENGINE=innoDB;;
1.2 MyISAMのテーブル。
SQL:

  1. CREATE TABLE IF NOT EXISTS entry2 (
  2.     `id`                         int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3.     `status`                     NUMERIC(5)    NOT NULL,
  4.     `category_id`                NUMERIC(10)   NOT NULL,
  5.     `user_type`                  NUMERIC(10)   NOT NULL,
  6.     `name`                       VARCHAR(64)   NOT NULL,
  7.     `favorites`                  NUMERIC(10)   NOT NULL,
  8.     `comments`                   NUMERIC(10)   NOT NULL,
  9.     `trackbacks`                 NUMERIC(10)   NOT NULL,
  10.     `comment_permission`         NUMERIC(10)   NOT NULL,
  11.     `trackback_permission`       NUMERIC(10)   NOT NULL,
  12.     `edited`                     DATETIME      NOT NULL,
  13.     `image`                      NUMERIC(10)   NULL,
  14.     `caption`                    VARCHAR(128)  NULL,
  15.     `user_name`                  VARCHAR(64)   NOT NULL,
  16.     `created`                    DATETIME      NOT NULL,
  17.     `modified`                   DATETIME      NOT NULL,
  18.     `removed`                    DATETIME      NULL,
  19.     `title`                      VARCHAR(1000) NOT NULL,
  20.     `body`                       TEXT          NULL,
  21.     `comment_captcha_permission` NUMERIC(10)   NOT NULL DEFAULT 1,
  22.     `favorite_permission`        NUMERIC(10)   NOT NULL DEFAULT 1,
  23.     PRIMARY KEY  (`id`),
  24.     UNIQUE INDEX `entry_unique` (`name`, `user_name`),
  25.     INDEX `entry_idx1` (`user_name`,`status`,`edited`),
  26.     INDEX `entry_idx2` (`name`,`user_name`,`removed`),
  27.     INDEX `entry_idx3` (`edited`),
  28.     INDEX `entry_idx4` (`trackbacks`,`edited`),
  29.     INDEX `entry_idx5` (`comments`,`edited`),
  30.     INDEX `entry_idx6` (`favorites`,`edited`),
  31.     INDEX `entry_idx7` (`category_id`,`edited`),
  32.     INDEX `entry_idx8` (`created`)
  33.     )“;
  34. CREATE TABLE IF NOT EXISTS entry_comment2 (
  35.     `id`                         int(10) unsigned NOT NULL auto_increment,
  36.     `guest_name`                 VARCHAR(300)  null,
  37.     `entry_id`                   NUMERIC(10)   not null,
  38.     `user_name`                  VARCHAR(64)   null,
  39.     `created`                    DATETIME      not null,
  40.     `removed`                    DATETIME      null,
  41.     `body`                       TEXT          null,
  42.     `guest_url`                  VARCHAR(1000) null,
  43.     PRIMARY KEY  (`id`),
  44.     INDEX `entry_comment_idx1` (`entry_id`,`created`,`removed`),
  45.     INDEX `entry_comment_idx2` (`user_name`,`removed`),
  46.     INDEX `entry_comment_idx3` (`removed`,`created`),
  47.     INDEX `entry_comment_idx4` (`user_name`)
  48.     )”;

要するに同じ構造でInnoDB(テーブル名:entry,entry_comment)、MyISAM(テーブル名:entry2,entry_comment2)用のテーブルを作成しました。

entryとentry2は記事を格納するテーブルで100万件登録されています。
entry_commentとentry_comment2はコメントを格納するテーブルで、こちらも100万件登録されています。

PRIMARY KEYであるidには1~1000000の値がセットされています。
1記事に対して、1コメントが存在しています。

2.show indexの結果

SQL:

  1. mysql> SHOW INDEX FROM entry;
  2. +——-+————+————–+————–+————-+———–+————-+———-+——–+——+————+———+
  3. | TABLE | Non_unique | Key_name     | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | NULL | Index_type | Comment |
  4. +——-+————+————–+————–+————-+———–+————-+———-+——–+——+————+———+
  5. | entry |          0 | PRIMARY      |            1 | id          | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  6. | entry |          0 | entry_unique |            1 | name        | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  7. | entry |          0 | entry_unique |            2 | user_name   | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  8. | entry |          1 | entry_idx1   |            1 | user_name   | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  9. | entry |          1 | entry_idx1   |            2 | STATUS      | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  10. | entry |          1 | entry_idx1   |            3 | edited      | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  11. | entry |          1 | entry_idx2   |            1 | name        | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  12. | entry |          1 | entry_idx2   |            2 | user_name   | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  13. | entry |          1 | entry_idx2   |            3 | removed     | A         |     1090408 |     NULL | NULL   | YES  | BTREE      |         |
  14. | entry |          1 | entry_idx3   |            1 | edited      | A         |        4161 |     NULL | NULL   |      | BTREE      |         |
  15. | entry |          1 | entry_idx4   |            1 | trackbacks  | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  16. | entry |          1 | entry_idx4   |            2 | edited      | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  17. | entry |          1 | entry_idx5   |            1 | comments    | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  18. | entry |          1 | entry_idx5   |            2 | edited      | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  19. | entry |          1 | entry_idx6   |            1 | favorites   | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  20. | entry |          1 | entry_idx6   |            2 | edited      | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  21. | entry |          1 | entry_idx7   |            1 | category_id | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  22. | entry |          1 | entry_idx7   |            2 | edited      | A         |     1090408 |     NULL | NULL   |      | BTREE      |         |
  23. | entry |          1 | entry_idx8   |            1 | created     | A         |        3894 |     NULL | NULL   |      | BTREE      |         |
  24. +——-+————+————–+————–+————-+———–+————-+———-+——–+——+————+———+
  25. 19 rows IN SET (0.66 sec)
  26.  
  27.  
  28. mysql> SHOW INDEX FROM entry_comment;
  29. +—————+————+——————–+————–+————-+———–+————-+———-+——–+——+————+———+
  30. | TABLE         | Non_unique | Key_name           | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | NULL | Index_type | Comment |
  31. +—————+————+——————–+————–+————-+———–+————-+———-+——–+——+————+———+
  32. | entry_comment |          0 | PRIMARY            |            1 | id          | A         |     1018735 |     NULL | NULL   |      | BTREE      |         |
  33. | entry_comment |          1 | entry_comment_idx1 |            1 | entry_id    | A         |     1018735 |     NULL | NULL   |      | BTREE      |         |
  34. | entry_comment |          1 | entry_comment_idx1 |            2 | created     | A         |     1018735 |     NULL | NULL   |      | BTREE      |         |
  35. | entry_comment |          1 | entry_comment_idx1 |            3 | removed     | A         |     1018735 |     NULL | NULL   | YES  | BTREE      |         |
  36. | entry_comment |          1 | entry_comment_idx2 |            1 | user_name   | A         |     1018735 |     NULL | NULL   | YES  | BTREE      |         |
  37. | entry_comment |          1 | entry_comment_idx2 |            2 | removed     | A         |     1018735 |     NULL | NULL   | YES  | BTREE      |         |
  38. | entry_comment |          1 | entry_comment_idx3 |            1 | removed     | A         |          18 |     NULL | NULL   | YES  | BTREE      |         |
  39. | entry_comment |          1 | entry_comment_idx3 |            2 | created     | A         |        3801 |     NULL | NULL   |      | BTREE      |         |
  40. | entry_comment |          1 | entry_comment_idx4 |            1 | user_name   | A         |     1018735 |     NULL | NULL   | YES  | BTREE      |         |
  41. +—————+————+——————–+————–+————-+———–+————-+———-+——–+——+————+———+
  42. 9 rows IN SET (0.31 sec)

3.同時スレッドを2,4,8,16,32,64と変えながら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 = 1024
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

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

上記の内容で計測したのは
InnoDB vs MyISAM パフォーマンス比較 Left Join
InnoDB vs MyISAM パフォーマンス比較 Inner Join
InnoDB vs MyISAM パフォーマンス比較 副問い合わせ
です。

 

関連会社インターオフィスのブログ記事を転載しています。

InnoDB vs MyISAMシリーズはまだまだ続きます。
前回はこちら
今回はLimitの件数の指定でどう変化するかと試してみます。

測定環境についてはこちらを参照して下さい。

・データ件数は100万件

こちらの構造のテーブルをInnoDBとMyISAMで作成して処理速度を比較

以下SQL中の「テーブル名 normal」にはMyISAMなら normal2 がセットされます。

8.INDEXで5000件のデータ 先頭50件

  SELECT name FROM normal WHERE country_id = %d LIMIT 50
 ※%dは1~200でランダムに変化
 ※country_idは1~200のランダム値で全体が100万件なので、非一意INDEXで5000件のうち先頭50件を取得します
 ※取得カラムはINDEX以外

INDEXで5000件のデータ 先頭50件
スレッド数 MyISAM InnoDB
1 1,210.67 1,352.00
2 1,994.00 1,975.33
4 1,991.00 1,962.00
8 2,000.00 1,855.00
16 1,972.67 1,681.00
32 1,851.33 1,585.33
64 1,735.33 1,494.00

INDEXで5000件のデータ 先頭50件


MyISAM 最高性能:最低性能= 1 : 0.87
InnoDB 最高性能:最低性能= 1 : 0.76

次に行きましょう。

9.INDEXで5000件のデータ 先頭5件

  SELECT name FROM normal WHERE country_id = %d LIMIT 5
 ※前述のLIMIT 50をLIMIT 5に変更しただけです。

INDEXで5000件のデータ 先頭5件
スレッド数 MyISAM InnoDB
1 2,873.33 3,582.67
2 4,652.33 5,115.67
4 4,650.33 5,112.33
8 4,657.00 4,941.00
16 4,436.00 4,311.67
32 3,887.33 3,722.67
64 3,577.33 3,447.00

INDEXで5000件のデータ 先頭5件


MyISAM 最高性能:最低性能= 1 : 0.77
InnoDB 最高性能:最低性能= 1 : 0.67

なるほど・・・・。

10.INDEXで5000件のデータ 先頭1件

  SELECT name FROM normal WHERE country_id = %d LIMIT 1
 ※前述のLIMIT 5をLIMIT 1に変更しただけです。

INDEXで5000件のデータ 先頭1件
スレッド数 MyISAM InnoDB
1 3,297.00 3,787.00
2 5,117.00 5,409.67
4 5,290.33 5,379.33
8 5,396.33 5,185.67
16 5,066.33 4,551.33
32 4,378.00 3,909.00
64 3,989.33 3,313.67

INDEXで5000件のデータ 先頭1件


MyISAM 最高性能:最低性能= 1 : 0.74
InnoDB 最高性能:最低性能= 1 : 0.61

ここまで見てくるとハッキリしたと思います。

  • データページに対するIOが多いクエリーの場合、(IOが少ないクエリーに比べて)遅いのは確かだが同時スレッド数による性能劣化が緩やか
  • ある程度以上IOが多いと同時スレッド数による性能劣化はなくなる(だからといってIOが多いのが良い訳ではないが)
  • MyISAMのほうが競合による性能劣化が緩やか
  • ただし性能を出し切る(グラフのピーク部分)ためは同時スレッド数を制御する必要がある
  • 同時スレッドを抑えるための仕組みが必要(これはまた今後の機会に)

とりあえずの結論です。

 

関連会社インターオフィスのブログ記事を転載しています。

なんかしつこいですがInnoDB vs MyISAMシリーズが続いています。

前回までではPrimaryKey,UniqueIndex、非UniqueIndexで1~数件を取得する
パターンが主ですが今回はそれなりの件数を取得するパターンを試してみます。

測定環境についてはこちらを参照して下さい。

・データ件数は100万件
こちらの構造のテーブルをInnoDBとMyISAMで作成して処理速度を比較

以下SQL中の「テーブル名 normal」にはMyISAMなら normal2 がセットされます。

6.INDEXで5000件のデータ取得

  SELECT name FROM normal WHERE country_id = %d
 ※%dは1~200でランダムに変化
 ※country_idは1~200のランダム値で全体が100万件なので、非一意INDEXで5000件のデータを取得します
 ※取得カラムはINDEX以外

INDEXで5000件のデータ取得
スレッド数 MyISAM InnoDB
1 20.00 23.00
2 32.00 33.00
4 32.00 31.67
8 32.67 30.33
16 32.00 30.00
32 32.00 28.67
64 31.33 27.00

INDEXで5000件のデータ取得


ますます同時スレッド数による性能劣化が緩やかになります。

MyISAMは同時スレッド数を上げても、性能がほとんど変化しません。。
スレッド数2~4くらいはほとんど互角です。

7.100万件テーブルスキャン MINを取得

  SELECT min(dob) FROM normal
 ※MINなのでFullScanの発生は確実

100万件テーブルスキャン MINを取得
スレッド数 MyISAM InnoDB
1 0.45 0.59
2 0.79 1.07
4 0.79 1.09/td>
8 0.82 1.14
16 0.84 1.18
32 0.84 1.20
64 0.93 1.20

100万件テーブルスキャン MINを取得


30~40%くらいInnoDBの方が高速です。
同時スレッド数上げても性能劣化が見られません。
というかかえってスループットが若干ですが向上します。

InnoDBとMyISAMの同時スレッドに対するスケーラビリィティの特性が関係が見えてきたような気がします。
次回、もう少し深追いして確認してみたいと思います。

 

関連会社インターオフィスのブログ記事を転載しています。

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以外

PrimaryKeyで一件検索
スレッド数 MyISAM InnoDB
1 6,674.33 6,948.33
2 11,003.33 11,520.00
4 11,432.00 12,012.00
8 11,219.33 11,205.00
16 9,774.67 9,292.00
32 8,638.67 7,497.00
64 6,618.00 5,965.33

PrimaryKeyで一件検索


前回も書いた通りほぼ「同点」です。
それにしても同時スレッドを上げるときれいに性能が落ちていきます。

2.UniqueIndexで一件検索

SELECT name FROM normal WHERE email = %s
 ※%sはランダムに変化
 ※取得カラムはINDEX以外

UniqueIndex一件検索
スレッド数 MyISAM InnoDB
1 3,906.00 4,010.33
2 6,634.33 6,702.67
4 6,602.67 6,677.33
8 6,229.00 6,270.00
16 5,979.33 5,793.67
32 5,161.67 5,034.33
64 4,929.33 4,534.33

UniqueIndex一件検索


これもほぼ「同点」と言ってよいと思います。
しかし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以外

PrimaryKeyで範囲検索
スレッド数 MyISAM InnoDB
1 1,008.00 1,792.67
2 1,627.00 2,812.67
4 1,632.67 2,825.00
8 1,652.00 2,760.67
16 1,640.67 2,536.33
32 1,627.33 2,299.33
64 1,528.67 2,097.33

PrimaryKeyで範囲検索



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件づつ取得する。

非UniqueIndexで範囲検索
スレッド数 MyISAM InnoDB
1 373.67 424.00
2 614.00 645.33
4 616.67 637.00
8 630.00 603.33
16 605.00 580.67
32 622.33 565.33
64 579.00 533.33

非UniqueIndexで範囲検索


これはほぼ同点です。
ただ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件を取得する。ただし取得時のソートなし。

非UniqueIndexで範囲検索 ソートなしで先頭5件を取得
スレッド数 MyISAM InnoDB
1 3,084.33 3,671.33
2 4,913.67 5,191.67
4 4,897.33 5,258.00
8 4,844.67 4,946.00
16 4,577.67 4,348.33
32 4,072.00 3,757.67
64 3,850.67 3,404.67

非UniqueIndexで範囲検索 ソートなしで先頭5件を取得


これもほぼ同点です。
ただ性能劣化の度合いが、「PrimaryKeyで1件取得」と「非UniqueIndexで範囲検索」の中間くらいですね。

まだまだ続きます

 

関連会社インターオフィスのブログ記事を転載しています。

innodb_thread_concurrencyとかでこんなことを書きました。

・innodb_thread_concurrency InnoDB の処理を同時に実行できるスレッド数の上限値
・MySQL 5.0.8 以降にデフォルト値が 8 から 20 に変更され、無制限を意味する値が 500 から 20 に変更されている
(つまり、デフォルトは制限なし)。
・最大スレッド数を無制限にすることで 10% 程度性能を上げることができた。

※自分で調べたのではなく、OSDL DBT-1 (ODBC版) による MySQL 5.0 性能測定 CPU 構成の差異による特性の分析と考察 Intel Xeon デュアルコア編 からの引用でした。

気になったので自分で計測してみました。

測定環境についてはこちらを参照して下さい。

・データ件数は100万件
こちらの構造のテーブルをInnoDBとMyISAMで作成して処理速度を比較

で、innodb_thread_concurrency を2,4,8,20(無制限を意味する)と変えながら計測してみました。

PrimaryKeyによるランダムアクセスの計測結果(innodb_thread_concurrency=2,4,8,20)
スレッド数 2 4 8 20
1 7,019.00 6,970.00 6,948.33 6,952.67
2 11,898.67 11,883.33 11,520.00 11,520.67
4 11,850.00 11,854.33 12,012.00 11,672.00
8 10,455.33 11,027.67 11,205.00 11,016.33
16 9,087.00 9,129.00 9,292.00 9,396.00
32 7,165.67 7,308.00 7,497.00 8,130.00
64 5,406.00 5,968.00 5,965.33 6,144.67
128 3,707.00 3,728.33 3,857.33 4,960.67

PrimaryKeyによるランダムアクセスの計測結果(innodb_thread_concurrency=2,4,8,20)


微妙ですね。

同時スレッド2,4,8だけでグラフにするとこんな感じです。

PrimaryKeyによるランダムアクセスの計測結果(innodb_thread_concurrency=2,4,8,20) 同時スレッド2,4,8だけ


innodb_thread_concurrency=2の場合
 同時スレッド2と4が性能が良い、同時スレッドを上げると急激に性能低下

innodb_thread_concurrency=4の場合
 同時スレッド2と4が性能が良い、同時スレッドを上げると時の落ち方がinnodb_thread_concurrency=2の場合より少し緩やか

innodb_thread_concurrency=8の場合
 同時スレッド4が他より性能が良い、同時スレッドを上げると時の落ち方がinnodb_thread_concurrency=2の場合より少し緩やか

innodb_thread_concurrency=20(無制限を意味する)の場合
 同時スレッド8に比べてピーク性能が落ちる 同時スレッドを上げると時の落ち方が他と比べて緩やか

といったところが特徴でしょう。

OSDL DBT-1 (ODBC版) による MySQL 5.0 性能測定 CPU 構成の差異による特性の分析と考察 Intel Xeon デュアルコア編 で、「最大スレッド数を無制限にすることで 10% 程度性能を上げることができた」のは、マシンスペックの問題でしょう。

あちらは

CPU: AMD Opteron 254 x 2 (2.8GHz, AMD64, L2 1MB)
Memory: 8GB (DDR/400, ECC)
Storage: 73GB (RAID1, 73GB x 2, SAS, 10000rpm, 2.5inch)
特徴:
シングルコア Opteron の最上位版 (2006年3月現在)
AMD64 (x86-64) 対応
SAS (Serial Attached SCSI) 接続で2.5インチのハードディスク

ですから、同時処理性能が高いためだと思います。

innodb_thread_concurrencyについてまとめると

・同時処理性能に影響はある
・CPUのコア数とディスク性能によって、設定値を決めるべき
・一般的なサーバ機(今時の1CPUデュアルコア以上+RAID)で、MySQL 5.0.8 以上ならば初期値の20でほぼ問題ないと思われる
・レベルの低いサーバの場合は、より少ない値に設定したほうがよい
・その場合は、CPUのコア数×2か3 くらいが目安になると思われる

ということになると思います。

 

関連会社インターオフィスのブログ記事を転載しています。