MyISAMのインデックスは、インデックスをディスクから読み出す際に、必ずキーバッファ(サイズはkey_buffer_sizeで指定)に一度乗るので、一度キーバッファに乗ったインデックスも、他のクエリによってキーバッファからこぼれることがあります。
そのため、「このテーブルのインデックスは常にキーバッファに乗せておいて高速化したい!」っていっても、デフォルトのキーバッファを使っている分には、いつこぼれるかわからず、常にメモリから読み出して、、ってことが保障できません。
#key_buffer_sizeを大きくすればするほどこぼれる確率は減ると思いますが、、
そこで、特定のインデックスに対してデフォルトとは別にキーバッファを確保することによって、常にキーバッファ上にそのインデックスを乗せておけるようなサイズを確保すれば良さげだなぁと、下記の読んで思いました。
- MySQL AB :: MySQL 5.1 リファレンスマニュアル :: 12.5.5.4 LOAD INDEX INTO CACHE 構文
- MySQL AB :: MySQL 5.1 リファレンスマニュアル :: 12.5.5.1 CACHE INDEX 構文
たとえば、hogeテーブルのインデックスを常にキーバッファに乗せておきたい!!って場合には、下記のような手順で設定します。
1. デフォルトとは別に、キーバッファを確保する。
SET GLOBAL hoge_cache.key_buffer_size=256*1024*1024;
この例では、hoge_cacheというキーキャッシュ名で、key_buffer_sizeを256M確保しています。なお、my.cnfで設定することも可能です。
2. 確保したキーバッファに対して、そのキーバッファを使用するインデックスを割り当てる。
CACHE INDEX hoge IN hoge_cache;
これで、hogeテーブルのインデックスは、デフォルトのキーバッファではなく、hoge_chaceに割り当てたキーバッファを使用するようになります。
3. インデックスを、あらかじめロードしておく。
LOAD INDEX INTO CACHE hoge;
hogeテーブルのインデックスを、キーバッファにロードします。これをMySQL起動時に行うことにより、常に該当のインデックスがキーバッファに置かれ、かつ他のテーブルに対するクエリに干渉されることがなくなります。
あとは、my.cnf の init_file にて、今までのSQL文をMySQL起動時に実行されるように設定しておきます。
なお、検証した感じでは、それっぽい動きをしてそうな感じはあるのですが、、、実際にちゃんと動いているのかが確認できません。
新たに確保したキーバッファに対する、Key_read_requestsとKey_readsが確認できれば、ちゃんとした確証が取れるのですが、デフォルトとは別に確保したキーバッファに対する情報を見る方法がわからず、確認できていません。(見た感じなさげ…)
ちなみに、該当のインデックスを使うようなSQLを実行しても、デフォルトのKey_read_requestsが増えないのは確認できているので、"CACHE INDEX"まではちゃんと効いている(デフォルトとは別のキーバッファが使われている)んだなぁというのは確認できています。
あと、実際key_buffer_sizeの値が妥当かまでみたいとなると、やはりKey_read_requestsとKey_readsを見ないと、、
ちゃんと想定した動きになるならば、パフォーマンスチューニングの一手段として、かなり使える方法じゃないかなぁと思います。
(tmpfsやramfsでメモリに乗せるよりかも手軽ですし)
あとはコレが正しいという確証をどうやって取るかってとこだけですね。
vmstatとかでIOの状況見ながら推測するしかないのかなぁ。。けど、OSのファイルキャッシュが絡んでくると、vmstatみただけではわからなそうな気が。。