MySQL 8.0で内部的に作成されるテンポラリテーブルが、HEAPストレージエンジンからTempTableストレージエンジンへと変更されたことは、皆さんもご存知だろう。このストレージエンジンはテンポラリテーブル専用として設計されたもので、実体を持ったテーブルとしての利用は想定していない。一応、internal_tmp_mem_storage_engineオプションを指定することで、従来のHEAPストレージエンジンも選択は可能であるが、個人的にはそれはお勧めしない。
TempTableストレージエンジンは、メモリとディスクの両方を自ら使い分ける。これは、従来型のテンポラリテーブルとは違う。HEAPストレージエンジンはインメモリ専用で、tmp_table_sizeあるいはmax_heap_table_sizeを超えるサイズが必要になると、ディスク上のテーブルへと自動的に変換が行われるという仕組みになっていた。当然ながら変換には時間がかかるので、これはオーバーヘッドが増える要因になっていた。MySQL 5.7ではディスク上テンポラリテーブルとして、InnoDBが選択できるようになったが、変換が生じる点は同じである。ちなみに、ディスク上のテンポラリテーブルは、internal_tmp_disk_storage_engineで指定可能である。
TempTableストレージエンジンは自らメモリとディスクを使い分けることができるので、そのような変換は発生しない。また、HEAPストレージエンジンは固定長のデータしか対応していないため、VARCHARなどの可変長のデータが必要になった場合には、最大サイズ分をメモリ上に確保するという非効率なことを行っている。当然ながら、後発であるTempTableストレージエンジンは、可変長のデータに対応しており、そのような効率的でないメモリの使い方はしない。
TempTableストレージエンジンのオプションには、temptable_max_ramというものしか存在しない。これは、TempTableストレージエンジンがMySQLサーバー全体で使用するメモリの総量を制限するものであり、テーブル単体ではない点に注意して欲しい。デフォルトサイズは1GBとなっているが、サーバー全体なので納得である。同時アクセス数が多い場合には、より大きなメモリサイズを割り当てた方が良い場合があるので、必要に応じて調整して欲しい。HEAPストレージエンジンでは、サーバー全体で消費するメモリサイズの総量制限はできなかったが、TempTableではその点が解消された。むしろ逆に総量制限しかできないようになっている点に注意して欲しい。
TempTableストレージエンジンがメモリを割り当てるかディスクを割り当てるかという判定は、極めて明確である。現在割り当てている総量+新たに必要な量がtemptable_max_ram以下ならメモリ、そうでないならディスクである。
メモリを割り当てる際には、malloc(3)あるいはnuma_alloc_local(3)が使われる。また、使い終わったメモリは即座にfree(3)あるいはnuma_free(3)で解放される。そのため、テンポラリテーブルが使われていない場合のメモリ消費はゼロとなる。メモリ消費がtemptable_max_ramのぶんだけ増減する可能性があるので注意して欲しい。(と言っても、実際にはlibc内でキャッシュされるので、OS上の見かけのメモリ消費は変わらないかも知れない。)
ディスクを割り当てる際には、tmpdirにテンポラリファイルを作成する。テンポラリファイルは作成された瞬間だけtmpdir上に現れるが、その後すぐにunlink(2)され、ディレクトリ上からは見えなくなる。そのようなファイルは、クローズされると実体がディスク上から削除される。このテンポラリファイルは、メモリ空間上にmmap(2)されるため、メモリと同じようにアクセスされる。つまり、TempTableストレージエンジン内では、メモリもディスクも同じようにアクセスされるようになっているワケである。ディスク上のデータとは言っても、間にファイルシステムキャッシュ等のバッファなどが入る点には注意されたい。従って、ディスクと言えどもそこまでアクセスが遅いわけではなく、ファイルシステムキャッシュに余裕があるうちは、それなりに高速なアクセスが可能であると考えられる。
そういうワケで、特にこだわりがなければ、MySQL 8.0ではテンポラリテーブル用の領域として、TempTableストレージエンジンを使うようにして欲しい。そして、問題が出た際にはバグ登録をして頂けると幸いである。
カスタム検索
0 コメント:
コメントを投稿