Yakstは、海外の役立つブログ記事などを人力で翻訳して公開するプロジェクトです。
8年以上前投稿 修正あり

MySQL 5.7の新機能 : パフォーマンススキーマのスケーラブルなメモリ割り当て(MySQL Server Blogより)

MySQL 5.7のパフォーマンススキーマ利用時のメモリ割り当て改善についてご紹介します

原文
New in MySQL 5.7: Performance Schema scalable memory allocation | MySQL Server Blog (English)
翻訳依頼者
D98ee74ffe0fafbdc83b23907dda3665 B5aa4f809000b9147289650532e83932
翻訳者
B5aa4f809000b9147289650532e83932 taka-h
翻訳レビュアー
D98ee74ffe0fafbdc83b23907dda3665 doublemarket
原著者への翻訳報告
未報告


免責事項

この記事は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確保しているのでしょうか。
  • : パフォーマンススキーマはどのインスタンスもメモリをそれぞれは確保せずある塊(チャンク)で確保します(17039361024のプリペアードステートメントです)。この確保されたチャンクは追加のインスタンスにそれ以上確保できなくなるまで利用されます。それからまた新しいチャンク(ここでは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とMariaDBの仮想列(Percona Data Performance Blogより)
前の記事
6万ミリ秒でできるLinuxパフォーマンス分析

Feed small 記事フィード

新着記事Twitterアカウント