WordPressのパフォーマンス向上の目的で、パフォーマンスチューニングを始めました。
httpd層では、別記事に記載したように、mod_chche、mod_disk_cacheを使用して、最低レベルの対策を実施しています。もちろん、まだ上のレベルがありますが、ここでは、DB層のパフォーマンスチューニングを実施します。
WordPressですので、DB層はMySQLです。現時点で最新のバージョン5.5.10を使用しています。
さて、まずは、現状を知ることから。
そこで、MySQLTuner を使用してみます。MySQLTuner は稼働中のMySQLの設定情報やログ情報からセキュリティ、パフォーマンスに関する診断結果と推奨情報を提供してくれるperlスクリプトです。
実際の利用には、まずは MySQLTuner をダウンロードします。
[root ~]# wget mysqltuner.pl --2011-03-30 12:51:21-- http://mysqltuner.pl/ mysqltuner.pl をDNSに問いあわせています... 50.56.84.181 mysqltuner.pl|50.56.84.181|:80 に接続しています... 接続しました。 HTTP による接続要求を送信しました、応答を待っています... 302 Found 場所: http://mysqltuner.pl/mysqltuner.pl [続く] --2011-03-30 12:51:22-- http://mysqltuner.pl/mysqltuner.pl mysqltuner.pl|50.56.84.181|:80 に接続しています... 接続しました。 HTTP による接続要求を送信しました、応答を待っています... 200 OK 長さ: 41393 (40K) [text/plain] `mysqltuner.pl' に保存中 100%[======================================>] 41,393 76.2K/s 時間 0.5s 2011-03-30 12:51:23 (76.2 KB/s) - `mysqltuner.pl' へ保存完了 [41393/41393]
1.現状把握
mysqltuner.pl を実行します。この際に念のため、httpdサービスを停止しておきます。現在の状態を維持したままで、チューニングを実施するためにMySQLへのアクセスを遮断する意味合いがあります。
[root ~]# perl mysqltuner.pl >> MySQLTuner 1.2.0 - Major Hayden>> Bug reports, feature requests, and downloads at http://mysqltuner.com/ >> Run with '--help' for additional options and output filtering [!!] Successfully authenticated with no password - SECURITY RISK! -------- General Statistics -------------------------------------------------- [--] Skipped version check for MySQLTuner script [OK] Currently running supported MySQL version 5.5.10-log [OK] Operating on 32-bit architecture with less than 2GB RAM -------- Storage Engine Statistics ------------------------------------------- [--] Status: +Archive -BDB -Federated +InnoDB -ISAM -NDBCluster [--] Data in InnoDB tables: 21M (Tables: 15) [--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17) [!!] Total fragmented tables: 15 -------- Security Recommendations ------------------------------------------- [!!] User 'root@127.0.0.1' has no password set. [!!] User 'root@::1' has no password set. [!!] User 'root@localhost' has no password set. [!!] User 'root@' has no password set. -------- Performance Metrics ------------------------------------------------- [--] Up for: 3d 14h 14m 4s (101K q [0.327 qps], 2K conn, TX: 359M, RX: 33M) [--] Reads / Writes: 86% / 14% [--] Total buffers: 210.0M global + 6.3M per thread (180 max threads) [!!] Maximum possible memory usage: 1.3G (87% of installed RAM) [OK] Slow queries: 0% (53/101K) [OK] Highest usage of available connections: 5% (10/180) [OK] Key buffer size / total MyISAM indexes: 32.0M/102.0K [OK] Key buffer hit rate: 96.4% (558 cached / 20 reads) [!!] Query cache efficiency: 0.0% (0 cached / 76K selects) [OK] Query cache prunes per day: 0 [OK] Sorts requiring temporary tables: 0% (0 temp sorts / 16K sorts) [!!] Temporary tables created on disk: 37% (7K on disk / 19K total) [OK] Thread cache hit rate: 99% (10 created / 2K connections) [!!] Table cache hit rate: 8% (59 open / 705 opened) [OK] Open file limit used: 4% (48/1K) [OK] Table locks acquired immediately: 100% (114K immediate / 114K locks) [OK] InnoDB data size / buffer pool: 21.1M/128.0M -------- Recommendations ----------------------------------------------------- General recommendations: Run OPTIMIZE TABLE to defragment tables for better performance Reduce your overall MySQL memory footprint for system stability When making adjustments, make tmp_table_size/max_heap_table_size equal Reduce your SELECT DISTINCT queries without LIMIT clauses Increase table_cache gradually to avoid file descriptor limits Variables to adjust: query_cache_limit (> 1M, or use smaller result sets) tmp_table_size (> 16M) max_heap_table_size (> 16M) table_cache (> 256)
この結果から次のようなことが分かります。
-
(1) rootによるローカルでのアクセスには、パスワードが設定されていない。
(2) Query cache(クエリキャッシュ)が利いていない。
(3) tmp_table_sizeが小さい。
(4) max_heap_table_sizeが小さい。
(5) table_cacheが小さい。
2.チューニング
ここからがチューニングです。
(1) パスワード
これについては、承知のことで、わざとこうしているので問題視していません。よって、このままで良しとします。
(2) Query cache(クエリキャッシュ)
これについては、「Recommendations」に出力されているように、 query_cache_limitの設定値を1MB超にすべしとのこと。
query_cache_limitとは、「この値を超える大きさのクエリ(結果)はキャッシュしない」という閾値のようです。
現在のmy.cnfには設定していません。
そこで次のようにして、実際の設定値を確認してみます。
[root ~]# mysqladmin -u root variables | grep query_cache | have_query_cache | YES | | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 16777216 | | query_cache_type | DEMAND | | query_cache_wlock_invalidate | OFF |
query_cache_limit は デフォルトで 1048576Byte(1MB余)になっているようです。これをもっと大きくすべしということです。大きなクエリ結果があるということなのでしょう。my.cnf にひとまず 2M として追加します。
query_cache_limit = 2M
ここで、query_cache_type が DEMAND になっているのを発見しました。query_cache_type の設定値は次のように3つあります。
query_cache_type =
-
0:キャッシュしない
1:SELECT SQL_NO_CACHE 以外のクエリをキャッシュする
2:SELECT SQL_CACHE のクエリだけをキャッシュする
キャッシュが利いていない直接の原因はこの設定のようです。ここでは 1 に変更します。
query_cache_type = 1
(3) tmp_table_size
tmp_table_size も my.cnf に設定していません。
デフォルトの設定を確認してみます。
[root ~]# mysqladmin -u root variables | grep tmp_table_size | tmp_table_size | 16777216 |
16MB余りであるようです。これをもっと大きくすべしとのことですので、my.cnf に次の設定を追加します。
tmp_table_size = 32M
(4) max_heap_table_size
max_heap_table_size も my.cnf に設定していません。
デフォルトの設定を確認してみます。
[root ~]# mysqladmin -u root variables | grep max_heap_table_size | max_heap_table_size | 16777216 |
16MB余りであるようです。
ただし、これについては、「Recommendations」の General recommendations に次のような記載があります。
When making adjustments, make tmp_table_size/max_heap_table_size equal
よって、上記(3)の tmp_table_size と同じ値で、次の設定を my.cnf に追加します。
max_heap_table_size = 32M
(5) table_cache
実は、table_cache はバージョン5.5にはありません。table_open_cache に変更になっています。
table_open_cache は my.cnf で 256 を指定していましたが、次のように変更します。
table_open_cache = 1024
MySQLTunerの実行結果に基づいたチューニングとしての設定変更はこれで終わりです。
3.MySQLの再起動
ここで、MySQLを再起動します。
[root ~]# service mysqld restart mysqld を停止中: [ OK ] mysqld を起動中: [ OK ]
4.チューニング結果検証
この状態で、再度 MySQLTuner を実行します。
[root ~]# perl mysqltuner.pl >> MySQLTuner 1.2.0 - Major Hayden>> Bug reports, feature requests, and downloads at http://mysqltuner.com/ >> Run with '--help' for additional options and output filtering [!!] Successfully authenticated with no password - SECURITY RISK! -------- General Statistics -------------------------------------------------- [--] Skipped version check for MySQLTuner script [OK] Currently running supported MySQL version 5.5.10-log [OK] Operating on 32-bit architecture with less than 2GB RAM -------- Storage Engine Statistics ------------------------------------------- [--] Status: +Archive -BDB -Federated +InnoDB -ISAM -NDBCluster [--] Data in InnoDB tables: 21M (Tables: 15) [--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17) [!!] Total fragmented tables: 15 -------- Security Recommendations ------------------------------------------- [!!] User 'root@127.0.0.1' has no password set. [!!] User 'root@::1' has no password set. [!!] User 'root@localhost' has no password set. [!!] User 'root@naboo' has no password set. -------- Performance Metrics ------------------------------------------------- [--] Up for: 10s (9 q [0.900 qps], 6 conn, TX: 10K, RX: 559) [--] Reads / Writes: 100% / 0% [--] Total buffers: 226.0M global + 6.3M per thread (180 max threads) [!!] Maximum possible memory usage: 1.3G (88% of installed RAM) [OK] Slow queries: 0% (0/9) [OK] Highest usage of available connections: 0% (1/180) [OK] Key buffer size / total MyISAM indexes: 32.0M/102.0K [!!] Key buffer hit rate: 50.0% (6 cached / 3 reads) [!!] Query cache efficiency: 0.0% (0 cached / 4 selects) [OK] Query cache prunes per day: 0 [OK] Temporary tables created on disk: 0% (0 on disk / 2 total) [OK] Thread cache hit rate: 83% (1 created / 6 connections) [OK] Table cache hit rate: 78% (26 open / 33 opened) [OK] Open file limit used: 0% (22/2K) [OK] Table locks acquired immediately: 100% (36 immediate / 36 locks) [!!] Connections aborted: 16% [OK] InnoDB data size / buffer pool: 21.3M/128.0M -------- Recommendations ----------------------------------------------------- General recommendations: Run OPTIMIZE TABLE to defragment tables for better performance MySQL started within last 24 hours - recommendations may be inaccurate Reduce your overall MySQL memory footprint for system stability Your applications are not closing MySQL connections properly Variables to adjust: query_cache_limit (> 2M, or use smaller result sets)
Query cache(クエリキャッシュ)はチューニングを始めた状態で利いていなかったわけですから、このままではいつまでもゼロのままです。
そこで、httpdを起動して、WordPressを少し使用してみます。
その後、改めて MySQLTuner を実行すると次のようになりました。
[root ~]# perl mysqltuner.pl >> MySQLTuner 1.2.0 - Major Hayden>> Bug reports, feature requests, and downloads at http://mysqltuner.com/ >> Run with '--help' for additional options and output filtering [!!] Successfully authenticated with no password - SECURITY RISK! -------- General Statistics -------------------------------------------------- [--] Skipped version check for MySQLTuner script [OK] Currently running supported MySQL version 5.5.10-log [OK] Operating on 32-bit architecture with less than 2GB RAM -------- Storage Engine Statistics ------------------------------------------- [--] Status: +Archive -BDB -Federated +InnoDB -ISAM -NDBCluster [--] Data in InnoDB tables: 21M (Tables: 15) [--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17) [!!] Total fragmented tables: 15 -------- Security Recommendations ------------------------------------------- [!!] User 'root@127.0.0.1' has no password set. [!!] User 'root@::1' has no password set. [!!] User 'root@localhost' has no password set. [!!] User 'root@naboo' has no password set. -------- Performance Metrics ------------------------------------------------- [--] Up for: 4m 43s (437 q [1.544 qps], 37 conn, TX: 1M, RX: 50K) [--] Reads / Writes: 87% / 13% [--] Total buffers: 226.0M global + 6.3M per thread (180 max threads) [!!] Maximum possible memory usage: 1.3G (88% of installed RAM) [OK] Slow queries: 0% (2/437) [OK] Highest usage of available connections: 1% (2/180) [OK] Key buffer size / total MyISAM indexes: 32.0M/102.0K [!!] Key buffer hit rate: 50.0% (6 cached / 3 reads) [OK] Query cache efficiency: 74.1% (254 cached / 343 selects) [OK] Query cache prunes per day: 0 [OK] Sorts requiring temporary tables: 0% (0 temp sorts / 9 sorts) [OK] Temporary tables created on disk: 14% (4 on disk / 27 total) [OK] Thread cache hit rate: 94% (2 created / 37 connections) [OK] Table cache hit rate: 88% (56 open / 63 opened) [OK] Open file limit used: 2% (52/2K) [OK] Table locks acquired immediately: 100% (95 immediate / 95 locks) [OK] InnoDB data size / buffer pool: 21.3M/128.0M -------- Recommendations ----------------------------------------------------- General recommendations: Run OPTIMIZE TABLE to defragment tables for better performance MySQL started within last 24 hours - recommendations may be inaccurate Reduce your overall MySQL memory footprint for system stability
ひとまず、これでチューニングを完了とします。
~~~~~~~~
実は、この後同様のチューニングを繰り返した結果、my.cnf のキャパシティに関する設定は次のようになりました。
[mysqld] max_connections = 180 key_buffer_size = 32M max_allowed_packet = 1M table_open_cache = 1024 tmp_table_size = 64M max_heap_table_size = 64M sort_buffer_size = 1M read_buffer_size = 1M read_rnd_buffer_size = 4M myisam_sort_buffer_size = 16M query_cache_type = 1 query_cache_size = 64M query_cache_limit = 4M thread_cache_size = 180 wait_timeout = 60 thread_concurrency = 4
~~~~~~~~
以下、「Recommendations」の「General recommendations」の出力に関して補足しておきます。
-
(※1) Run OPTIMIZE TABLE to defragment tables for better performance について
別途、方法論も検討して、実施していきたいと思います。
(※2) MySQL started within last 24 hours – recommendations may be inaccurate について
これは、MySQLを再起動したばかりなので、正確な診断結果ではないということを断っているだけです。
(※3) Reduce your overall MySQL memory footprint for system stability について
「システムの安定化のためには、MySQLが必要とする全メモリを少なくした方がいい」という意味と理解しました。運用中のメモリリソース状況を監視しながら、適正化していきたいと思います。