MySQL はバッファおよびキャッシュを割り当てて、データベース操作のパフォーマンスを向上させます。 デフォルトの構成は、RAM が約 512MB の仮想マシンで MySQL サーバーを起動できるように設計されています。 特定のキャッシュおよびバッファ関連のシステム変数の値を増やすことで、MySQL のパフォーマンスを向上できます。 メモリーが制限されたシステムで MySQL を実行するように、デフォルトの構成を変更することもできます。
次のリストでは、MySQL がメモリーを使用する方法をいくつか説明します。 該当する場合は、関連するシステム変数が参照されます。 ストレージエンジンまたは機能固有の項目もあります。
-
InnoDB
バッファプールは、テーブル、インデックスおよびその他の補助バッファのキャッシュされたInnoDB
データを保持するメモリー領域です。 大容量読み取り操作の効率を高めるため、バッファープールは複数行を保持できるページに分割されます。 キャッシュ管理の効率のために、バッファープールはページのリンクリストとして実装されます。まれにしか使用されないデータは、LRU アルゴリズムのバリエーションを使用してキャッシュからエージアウトされます。 詳細は、セクション15.5.1「バッファプール」を参照してください。バッファプールのサイズは、システムパフォーマンスのために重要です:
InnoDB
は、malloc()
操作を使用して、サーバー起動時にバッファプール全体にメモリーを割り当てます。innodb_buffer_pool_size
システム変数は、バッファープールサイズを定義します。 通常、推奨されるinnodb_buffer_pool_size
値は、システムメモリーの 50 から 75% です。innodb_buffer_pool_size
は、サーバーの実行中に動的に構成できます。 詳細は、セクション15.8.3.1「InnoDB バッファプールサイズの構成」を参照してください。メモリーが大量にあるシステムでは、バッファプールを複数の buffer pool instances に分割することで同時実行性を向上させることができます。
innodb_buffer_pool_instances
システム変数は、バッファープールインスタンスの数を定義します。バッファプールが小さすぎると、ページがバッファプールからフラッシュされるときに、後で再度必要になるだけであるため、過剰なチャーニングが発生する可能性があります。
バッファプールが大きすぎると、メモリーの競合が原因でスワッピングが発生する場合があります。
ストレージエンジンインタフェースを使用すると、オプティマイザは、オプティマイザが複数の行を読み取る可能性が高いスキャンに使用されるレコードバッファーのサイズに関する情報を提供できます。 バッファサイズは、見積りのサイズによって異なる場合があります。
InnoDB
では、この可変サイズのバッファリング機能を使用して、行プリフェッチを利用し、ラッチおよび B ツリーナビゲーションのオーバーヘッドを削減します。-
すべてのスレッドが
MyISAM
キーバッファを共有します。key_buffer_size
システム変数によってサイズが決まります。サーバーが開く
MyISAM
テーブルごとに、インデックスファイルが一度開かれます。テーブルにアクセスする同時に実行されているスレッドごとに、データファイルが一度開かれます。 同時スレッドごとに、テーブル構造、各カラムのカラム構造、およびサイズ3 *
のバッファーが割り当てられます (ここでN
N
は最大行長で、BLOB
カラムをカウントしていません)。BLOB
カラムには、5 から 8 バイト+BLOB
データの長さが必要です。MyISAM
ストレージエンジンは、内部使用のため 1 つ余分な行バッファーを保持します。 myisam_use_mmap
システム変数を 1 に設定して、すべてのMyISAM
テーブルのメモリーマッピングを有効にできます。-
内部インメモリー一時テーブルが大きすぎる場合 (
tmp_table_size
およびmax_heap_table_size
システム変数を使用して決定)、MySQL はテーブルをインメモリーからディスク上の形式に自動的に変換します。 MySQL 8.0.16 の時点では、ディスク上の一時テーブルは常に InnoDB ストレージエンジンを使用します。 (以前は、この目的に使用されていたストレージエンジンは、サポートされなくなったinternal_tmp_disk_storage_engine
システム変数によって決定されていました。) セクション8.4.4「MySQL での内部一時テーブルの使用」に説明するように、許可される一時テーブルのサイズを増やすことができます。CREATE TABLE
を使用して明示的に作成されたMEMORY
テーブルの場合、max_heap_table_size
システム変数のみがテーブルの大きさを決定し、ディスク上の形式への変換はありません。 MySQL Performance Schema は、MySQL サーバーの実行を低レベルで監視するための機能です。 パフォーマンススキーマは、サーバーの起動時に必要なメモリーを割り当てるのではなく、メモリー使用量を実際のサーバー負荷に合わせて増分的に割り当てます。 割り当てられたメモリーは、サーバーが再起動されるまで解放されません。 詳細は、セクション27.17「パフォーマンススキーマのメモリー割り当てモデル」を参照してください。
-
サーバーがクライアント接続の管理に使用する各スレッドには、スレッド固有の領域が必要です。 次のリストは、これらの変数とそのサイズを制御するシステム変数を示しています:
スタック (
thread_stack
)接続バッファ (
net_buffer_length
)結果バッファ (
net_buffer_length
)
接続バッファーと結果バッファーはそれぞれ
net_buffer_length
バイトに等しいサイズから開始されますが、必要に応じてmax_allowed_packet
バイトまで動的に拡大されます。 結果バッファーは各 SQL ステートメントのあとにnet_buffer_length
バイトに縮小されます。 ステートメントの実行中は現在のステートメント文字列のコピーも割り当てられます。各接続スレッドは、ステートメントダイジェストの計算にメモリーを使用します。 サーバーは、セッションごとに
max_digest_length
バイトを割り当てます。 セクション27.10「パフォーマンススキーマのステートメントダイジェストとサンプリング」を参照してください。 すべてのスレッドで同じベースメモリーを共有します。
スレッドが必要ない場合、それに割り当てられたメモリーが解放され、スレッドがスレッドキャッシュに戻らないかぎり、システムに返されます。 その場合、メモリーは割り当てられた状態のままになります。
テーブルの順次スキャンを実行する各リクエストによって、read buffer が割り当てられます。
read_buffer_size
システム変数によってバッファサイズが決まります。任意の順序 (ソート後など) で行を読み取る場合、ディスクシークを回避するためにランダム読取りバッファを割り当てることができます。
read_rnd_buffer_size
システム変数によってバッファサイズが決まります。すべての結合は単一のパスで実行され、ほとんどの結合は一時テーブルも使用せずに実行できます。 ほとんどの一時テーブルはメモリーベースのハッシュテーブルです。 大きな行長 (すべてのカラム長の合計として算出される) を持つか
BLOB
カラムを含む一時テーブルはディスク上に格納されます。ソートを実行するほとんどのリクエストは、ソートバッファーおよび結果セットサイズに応じた 0 から 2 つの一時ファイルを割り当てます。 セクションB.3.3.5「MySQL が一時ファイルを格納する場所」を参照してください。
ほとんどすべての解析と計算は、スレッドローカルの再利用可能なメモリープールで実行されます。 小さい項目にはメモリーオーバーヘッドは必要ないため、通常の低速メモリー割当ておよび解放が回避されます。 メモリーは、予測外に大きな文字列にのみ割り当てられます。
BLOB
カラムがあるテーブルごとに、大きなBLOB
値を読み取るためにバッファーが動的に拡大されます。 テーブルをスキャンすると、バッファは最大のBLOB
値と同じ大きさになります。-
MySQL には、テーブルキャッシュ用のメモリーおよびディスクリプタが必要です。 使用中のすべてのテーブルのハンドラ構造はテーブルキャッシュに保存され、「「先入れ先出し」」 (FIFO) として管理されます。
table_open_cache
システム変数は、初期テーブルキャッシュサイズを定義します。セクション8.4.3.1「MySQL でのテーブルのオープンとクローズの方法」 を参照してください。MySQL には、テーブル定義キャッシュ用のメモリーも必要です。
table_definition_cache
システム変数は、テーブル定義キャッシュに格納できるテーブル定義の数を定義します。 多数のテーブルを使用する場合は、大規模なテーブル定義キャッシュを作成してテーブルのオープンを高速化できます。 テーブル定義キャッシュは、テーブルキャッシュとは異なり、使用する領域が少なく、ファイル記述子を使用しません。 FLUSH TABLES
ステートメントまたは mysqladmin flush-tables コマンドは、使用中でないすべてのテーブルを一度に閉じ、現在実行中のスレッドの終了時に閉じられるように使用中のすべてのテーブルをマークします。 これにより、事実上ほとんどの使用中のメモリーが解放されます。FLUSH TABLES
はすべてのテーブルが閉じられるまで戻りません。GRANT
、CREATE USER
、CREATE SERVER
、およびINSTALL PLUGIN
ステートメントの結果として、サーバーは情報をメモリーにキャッシュします。 このメモリーは、対応するREVOKE
,DROP USER
,DROP SERVER
ステートメントおよびUNINSTALL PLUGIN
ステートメントによって解放されないため、キャッシュを引き起こすステートメントの多くのインスタンスを実行するサーバーでは、FLUSH PRIVILEGES
で解放されないかぎり、キャッシュされたメモリーの使用量が増加します。-
レプリケーショントポロジでは、次の設定はメモリー使用量に影響し、必要に応じて調整できます:
レプリケーションソースの
max_allowed_packet
システム変数は、ソースが処理のためにレプリカに送信する最大メッセージサイズを制限します。 この設定のデフォルトは 64M です。マルチスレッドレプリカ上の
slave_pending_jobs_size_max
システム変数は、処理待ちのメッセージを保持するために使用できるメモリーの最大量を設定します。 この設定のデフォルトは 128M です。 メモリーは必要な場合にのみ割り当てられますが、レプリケーショントポロジが大規模なトランザクションを処理する場合に使用されることがあります。 これは弱い制限であり、より大きなトランザクションを処理できます。レプリケーションソースまたはレプリカ上の
rpl_read_size
システム変数は、バイナリログファイルおよびリレーログファイルから読み取られるデータの最小量をバイト単位で制御します。 デフォルトは 8192 バイトです。 バイナリログおよびリレーログファイルから読み取るスレッドごとに、この値のバッファーが割り当てられます。これには、ソース上のダンプスレッドやレプリカ上のコーディネータスレッドも含まれます。binlog_transaction_dependency_history_size
システム変数は、インメモリー履歴として保持される行ハッシュの数を制限します。max_binlog_cache_size
システム変数は、個々のトランザクションによるメモリー使用量の上限を指定します。max_binlog_stmt_cache_size
システム変数は、ステートメントキャッシュによるメモリー使用量の上限を指定します。
ps およびその他のステータスプログラムが、mysqld が大量のメモリーを使用していることをレポートすることがあります。 これは、さまざまなメモリーアドレス上のスレッドスタックによって発生する可能性があります。 たとえば、Solaris バージョンの ps はスタック間の未使用のメモリーが使用されているメモリーとしてカウントされます。 これを確認するには、swap -s
で使用可能なスワップをチェックします。 いくつかのメモリーリーク検出ツール (市販とオープンソースの両方の) で mysqld をテストしているため、メモリーリークはないはずです。
次の例は、Performance Schema および sys schema を使用して MySQL メモリー使用量を監視する方法を示しています。
ほとんどのパフォーマンススキーマメモリーインストゥルメンテーションはデフォルトで無効になっています。 インストゥルメントを有効にするには、パフォーマンススキーマ setup_instruments
テーブルの ENABLED
カラムを更新します。 メモリーインストゥルメントには memory/
という形式の名前が付けられます。ここで、code_area
/instrument_name
code_area
は sql
や innodb
などの値で、instrument_name
はインストゥルメントの詳細です。
-
使用可能な MySQL メモリーインストゥルメントを表示するには、パフォーマンススキーマの
setup_instruments
テーブルをクエリーします。 次のクエリーは、すべてのコード領域に対して何百ものメモリーインストゥルメントを返します。mysql> SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory%';
コード領域を指定して結果を絞り込むことができます。 たとえば、コード領域として
innodb
を指定することで、結果をInnoDB
メモリーインストゥルメントに制限できます。mysql> SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory/innodb%'; +-------------------------------------------+---------+-------+ | NAME | ENABLED | TIMED | +-------------------------------------------+---------+-------+ | memory/innodb/adaptive hash index | NO | NO | | memory/innodb/buf_buf_pool | NO | NO | | memory/innodb/dict_stats_bg_recalc_pool_t | NO | NO | | memory/innodb/dict_stats_index_map_t | NO | NO | | memory/innodb/dict_stats_n_diff_on_level | NO | NO | | memory/innodb/other | NO | NO | | memory/innodb/row_log_buf | NO | NO | | memory/innodb/row_merge_sort | NO | NO | | memory/innodb/std | NO | NO | | memory/innodb/trx_sys_t::rw_trx_ids | NO | NO | ...
MySQL のインストールによっては、コード領域に
performance_schema
,sql
,client
,innodb
,myisam
,csv
,memory
,blackhole
,archive
,partition
などが含まれる場合があります。 -
メモリーインストゥルメントを有効にするには、MySQL 構成ファイルに
performance-schema-instrument
ルールを追加します。 たとえば、すべてのメモリーインストゥルメントを有効にするには、このルールを構成ファイルに追加し、サーバーを再起動します:performance-schema-instrument='memory/%=COUNTED'
注記起動時にメモリーインストゥルメントを有効にすると、起動時に発生するメモリー割り当てが確実にカウントされます。
サーバーを再起動したあと、パフォーマンススキーマ
setup_instruments
テーブルのENABLED
カラムに、有効にしたメモリーインストゥルメントのYES
が報告されます。 メモリー操作が時間指定されていないため、setup_instruments
テーブルのTIMED
カラムはメモリーインストルメントで無視されます。mysql> SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%memory/innodb%'; +-------------------------------------------+---------+-------+ | NAME | ENABLED | TIMED | +-------------------------------------------+---------+-------+ | memory/innodb/adaptive hash index | NO | NO | | memory/innodb/buf_buf_pool | NO | NO | | memory/innodb/dict_stats_bg_recalc_pool_t | NO | NO | | memory/innodb/dict_stats_index_map_t | NO | NO | | memory/innodb/dict_stats_n_diff_on_level | NO | NO | | memory/innodb/other | NO | NO | | memory/innodb/row_log_buf | NO | NO | | memory/innodb/row_merge_sort | NO | NO | | memory/innodb/std | NO | NO | | memory/innodb/trx_sys_t::rw_trx_ids | NO | NO | ...
-
メモリーインストゥルメントデータをクエリーします。 この例では、メモリーインスツルメントデータがパフォーマンススキーマ
memory_summary_global_by_event_name
テーブルでクエリーされ、EVENT_NAME
によってデータが要約されます。EVENT_NAME
はインストゥルメントの名前です。次のクエリーは、
InnoDB
バッファプールのメモリーデータを返します。 カラムの説明は、セクション27.12.18.10「メモリーサマリーテーブル」 を参照してください。mysql> SELECT * FROM performance_schema.memory_summary_global_by_event_name WHERE EVENT_NAME LIKE 'memory/innodb/buf_buf_pool'\G EVENT_NAME: memory/innodb/buf_buf_pool COUNT_ALLOC: 1 COUNT_FREE: 0 SUM_NUMBER_OF_BYTES_ALLOC: 137428992 SUM_NUMBER_OF_BYTES_FREE: 0 LOW_COUNT_USED: 0 CURRENT_COUNT_USED: 1 HIGH_COUNT_USED: 1 LOW_NUMBER_OF_BYTES_USED: 0 CURRENT_NUMBER_OF_BYTES_USED: 137428992 HIGH_NUMBER_OF_BYTES_USED: 137428992
同じ基礎となるデータを
sys
スキーマmemory_global_by_current_bytes
テーブルを使用してクエリーすることができます。このテーブルには、グローバルにサーバー内の現在のメモリー使用量が割当てタイプ別に分類されて表示されます。mysql> SELECT * FROM sys.memory_global_by_current_bytes WHERE event_name LIKE 'memory/innodb/buf_buf_pool'\G *************************** 1. row *************************** event_name: memory/innodb/buf_buf_pool current_count: 1 current_alloc: 131.06 MiB current_avg_alloc: 131.06 MiB high_count: 1 high_alloc: 131.06 MiB high_avg_alloc: 131.06 MiB
この
sys
スキーマクエリーは、現在割り当てられているメモリー (current_alloc
) をコード領域別に集計します:mysql> SELECT SUBSTRING_INDEX(event_name,'/',2) AS code_area, FORMAT_BYTES(SUM(current_alloc)) AS current_alloc FROM sys.x$memory_global_by_current_bytes GROUP BY SUBSTRING_INDEX(event_name,'/',2) ORDER BY SUM(current_alloc) DESC; +---------------------------+---------------+ | code_area | current_alloc | +---------------------------+---------------+ | memory/innodb | 843.24 MiB | | memory/performance_schema | 81.29 MiB | | memory/mysys | 8.20 MiB | | memory/sql | 2.47 MiB | | memory/memory | 174.01 KiB | | memory/myisam | 46.53 KiB | | memory/blackhole | 512 bytes | | memory/federated | 512 bytes | | memory/csv | 512 bytes | | memory/vio | 496 bytes | +---------------------------+---------------+
注記MySQL 8.0.16 より前は、
sys.format_bytes()
はFORMAT_BYTES()
に使用されていました。sys
スキーマの詳細は、第28章「MySQL sys スキーマ」 を参照してください。