免責事項
この記事はMayank Prasad氏によるMySQL Server Blogの投稿「New in MySQL 5.7: Performance Schema scalable memory allocation」(2016/2/11)をユーザが翻訳したものであり、Oracle公式の文書ではありません。
パフォーマンススキーマは実行中のMySQLサーバーの実行時間の統計を収集しレポートする仕組みです。これらの統計は内部のメモリバッファーに保存され、またそこから取得されます。MySQL 5.6 GA版では、これらのバッファーはユーザー指定のコンフィグ値であっても自動でサイズが決まるデフォルト値であっても、MySQLサーバーの起動時に確保されます。一度サーバーが起動されればバッファーサイズは固定化され、パフォーマンススキーマは実行中に追加でメモリを確保しませんし解放もしません。
固定化されたメモリの確保はいくつか制限事項を発生させます。ユーザーがパフォーマンススキーマに値を指定した場合、あるいはデフォルト値を利用した場合に発生しうる2つのシチュエーションの概要は次の通りです。
- [懸念事項1] インストゥルメントのインスタンスがあまり使われないと、確保されたメモリの多くが利用されないままとなる
- [懸念事項2] メモリ確保が十分でない状態で、インストゥルメントのインスタンスが多く使われると、パフォーマンススキーマの追加の統計情報が失われはじめる
これによって次のような疑問が発生します。つまりパフォーマンススキーマ自身でバッファーの最適なサイズはどのくらいの大きさでサーバーの負荷に応じて変更できる方法はあるか?そして、それは実現可能なのか?、です。
そうです!MySQL 5.7 GA版のパフォーマンススキーマではこの機能を提供しているのです。
MySQL 5.7の変更点
MySQL 5.7ではパフォーマンススキーマのバッファーのメモリ確保はサーバー起動時に行われず、代わりに実際に必要になったタイミングで行われます。
バッファーサイズを制御するサーバー変数としては次のものを指定可能です。
- 0: パフォーマンススキーマに統計情報収集しないようにする。バッファーは確保されない。
- N: パフォーマンススキーマに最大Nインスタンス統計情報収集するようにする。必要になったタイミングでメモリが確保される。確保は最大数(ここではN)のインスタンスが確保されるまで行われる。
- -1: パフォーマンススキーマに上限値を自律的に決定させる。上記同様必要な際に確保される。確保は最大数のインスタンス(ここではパフォーマンススキーマ自身が決定)が確保されるまで行われる。
それでは次の例について考えてみましょう
[懸念事項1] インストゥルメントのインスタンスがあまり使われないと、確保されたメモリの多くが利用されないままとなる
最大2000のプリペアードステートメントの統計情報を収集する想定でMySQLサーバーを起動します。
mysqld --performance_schema_max_prepared_statements_instances=2000
クライアントを起動してプリペアードステートメントに対する統計を保存するためのバッファー用のメモリ確保についてみてみましょう。
mysql > show engine performance_schema status;
+--------------------+--------------------------------------+----------+
| Type | Name | Status |
+--------------------+--------------------------------------+----------+
...
| performance_schema | prepared_statements_instances.size | 1664 |
| performance_schema | prepared_statements_instances.count | 0 |
| performance_schema | prepared_statements_instances.memory | 0 |
...
+--------------------+--------------------------------------+----------+
229 rows in set (0.00 sec)
現在のところサーバー上にはプリペアードステートメントは1つもないので、バッファー用のメモリは確保されていません。
ステートメントをプリペアーしてみましょう。
mysql > prepare stmt1 from 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
Query OK, 0 rows affected (0.00 sec)
Statement prepared
次の通り確保されたバッファーサイズを確認できます
mysql > show engine performance_schema status;
+--------------------+--------------------------------------+----------+
| Type | Name | Status |
+--------------------+--------------------------------------+----------+
...
| performance_schema | prepared_statements_instances.size | 1664 |
| performance_schema | prepared_statements_instances.count | 1024 |
| performance_schema | prepared_statements_instances.memory | 1703936 |
...
+--------------------+--------------------------------------+----------+
229 rows in set (0.01 sec)
お分かりのように、数字が変わっていて、メモリーが必要となったため確保されました。
- 質問: サーバー上には1つのプリペアードステートメントしかなく、1つのプリペアードステートメント統計情報に必要なメモリは1664です。なぜパフォーマンススキーマは1703936確保しているのでしょうか。
- 答: パフォーマンススキーマはどのインスタンスもメモリをそれぞれは確保せずある塊(チャンク)で確保します(1703936は1024のプリペアードステートメントです)。この確保されたチャンクは追加のインスタンスにそれ以上確保できなくなるまで利用されます。それからまた新しいチャンク(ここでは1703936)を最大値Nを超えない限り再度確保します。この値(N)はユーザーが指定できます(あるいは-1が指定された場合はパフォーマンススキーマが決定します)。
パフォーマンススキーマのバッファーのメモリ確保をこの機能ができる前後で比較すると次のようになります。
[懸念事項2] メモリ確保が十分でない状態で、インストゥルメントのインスタンスが多く使われると、パフォーマンススキーマの追加の統計情報が失われはじめる
インストゥルメントが大量に発生することを予測できない場合、この問題を解決するために、変数の値に-1を指定することができます。この例では実行中に必要に応じてメモリを確保します。 例えば(誤って)2000のプリペアードステートメントを見積もったものの、実行中に3000のプリペアードステートメントが現れた場合、次のようになります。
オートスケーリングが実装される前:
mysql > show variables like 'performance_schema_max_prepared_statements_instances';
+------------------------------------------------------+-------+
| Variable_name | Value |
+------------------------------------------------------+-------+
| performance_schema_max_prepared_statements_instances | 2000 |
+------------------------------------------------------+-------+
1 row in set (0.00 sec)
mysql> show status like "%prepared_statements_lost%";
+-----------------------------------------------+-------+
| Variable_name | Value |
+-----------------------------------------------+-------+
...
| Performance_schema_prepared_statements_lost | 1000 |
...
+-----------------------------------------------+-------+
1000インスタンスの統計が失われていることが分かります。
現在(オートスケーリングあり):
mysql > show variables like 'performance_schema_max_prepared_statements_instances';
+------------------------------------------------------+-------+
| Variable_name | Value |
+------------------------------------------------------+-------+
| performance_schema_max_prepared_statements_instances | -1 |
+------------------------------------------------------+-------+
1 row in set (0.00 sec)
mysql> show status like "%prepared_statements_lost%";
+-----------------------------------------------+-------+
| Variable_name | Value |
+-----------------------------------------------+-------+
...
| Performance_schema_prepared_statements_lost | 0 |
...
+-----------------------------------------------+-------+
全インスタンスの統計が収集され何一つロストしていません。
非常に重要なことをもう1つお伝えせねばならず、パフォーマンススキーマのバッファー用に実行中に確保されたメモリは、決して解放されません。
パフォーマンススキーマのバッファーサイズを制御するサーバー変数は、オートスケールさせるようにすることも可能で(値を-1に設定可能)、デフォルト値は-1です。ここにこれらのサーバー変数の一覧を記します。
mysql> show variables where variable_name like "performance_schema%" and variable_value=-1;
+------------------------------------------------------+-------+
| Variable_name | Value |
+------------------------------------------------------+-------+
| performance_schema_accounts_size | -1 |
| performance_schema_hosts_size | -1 |
| performance_schema_max_cond_instances | -1 |
| performance_schema_max_file_instances | -1 |
| performance_schema_max_index_stat | -1 |
| performance_schema_max_metadata_locks | -1 |
| performance_schema_max_mutex_instances | -1 |
| performance_schema_max_prepared_statements_instances | -1 |
| performance_schema_max_program_instances | -1 |
| performance_schema_max_rwlock_instances | -1 |
| performance_schema_max_socket_instances | -1 |
| performance_schema_max_table_handles | -1 |
| performance_schema_max_table_instances | -1 |
| performance_schema_max_table_lock_stat | -1 |
| performance_schema_max_thread_instances | -1 |
| performance_schema_setup_actors_size | -1 |
| performance_schema_setup_objects_size | -1 |
| performance_schema_users_size | -1 |
+------------------------------------------------------+-------+
18 rows in set, 1 warning (0.01 sec)
自動サイズ(auto-sized)と自動スケール(auto-scaled)のパフォーマンススキーマ変数の違い
上記の(自動スケール)変数は自動サイズの変数を混同してはいけません。自動サイズの変数はサーバー起動時でも-1に設定できますが、次のような違いがあります。
- 自動サイズ
- サーバーの負荷予測および設定値に基づき、サーバー起動時にパフォーマンスキーマによって変数の値が決定されます。
- 自動スケール
- 実際の実行中の要求に合わせ、バッファーのメモリがこれらの変数に制御され確保されます。
訳注
下記ドキュメントも合わせてご活用ください
- パフォーマンマンススキーマ起動構成 (MySQL 5.6、日本語、自動サイズ関連)
- パフォーマンススキーマメモリーモデル(MySQL 5.7、英語)