コスいチューニング

全く本質的でなく効果も小さいものばかりだけど、最後のひと絞りにどうぞ。

Hardware

  • HT無効

今時サーバでNetBurstもないだろうけど、使っているなら切った方が速い。並列実行度が高くなるには違いないが、spin lockとHTは相性がよろしくないし、そもそもNetBurstのHTは速くなる局面が少なすぎる。いっぱいプロセッサが見えるのは気持ちいいが、実効性能を考えると無効の方が速い。

  • RAID1+0

ブロックサイズは大きめで(256KBとか)にする。"1つのレコードの大きさ <= RIADのブロックサイズ"である状態だと、RAIDを構成する複数のディスクのうち1個へのリクエストで処理が完結するので具合が良い。逆に"1つのレコードの大きさ > RAIDのブロックサイズ"であると、1レコードの読み出しにも2個のディスクがその処理にかかり切りになってしまう。HDDの毎秒の処理回数は上限が決まっていてかつ、原理的に性能限界が低いところにあるためボトルネックになり易い貴重な資源である。極力浪費は避けるべし。

Linuxカーネル

  • deadline I/O scheduler

最近の2.6.xでの標準はCFQだけど、これを変更する。
deadlineとは遅延を最小にすることを目標にしたスケジューラ。DBのようにランダムなI/Oでブロックが多発するような場合には向くスケジューラ。起動時や/sys/block//queue/schedulerに現在使っているスケジューラと代替のスケジューラが表示されていればブロックデバイス単位で実行中に動的に変更可能。さもなくば起動時のオプションで指定する。
単純なマイクロベンチマークなどで測るとI/Oのスループットは落ちるかも。稼ぎたいのはスループットではなくレイテンシなのでこれは仕方無い。

  • VMのパラメータ調整

/proc/syc/vm/* (あるいはsysctlのvm.*)でブロックバッファに関連するパラメータを調整する。
書き込みバッファはRAIDカードのライトバックバッファに任せて、OSのブロックバッファは読み込みをキャッシュする方向でチューニング。

  • 先読みの抑止

小さいブロックのランダムアクセスが多いにもかかわらずデバイスに対して大きな量の先読みを行っているようならば、これを抑止する。
具体的にはccissデバイスは標準で4MBの先読みを行うような設定となっているが、これは大き過ぎるケースがある。先読みブロックを小さくするか無効にする。(cf /sys/block/cciss/queue/read_ahead_kb)

  • noatime

atimeを使う場面はあまり大くないため、ペナルティは皆無。
mountオプションとしてfstabに書く。わりと定石。

  • nodiratime

実はdir自体にもatimeがあって、これはその更新処理を抑止するオプション。
いくつかのファイルシステムでコードを読んだ限りではnoatimeを有効にしていれば、こちらは不要なはず。

MySQL

  • query_cache

データの更新頻度が低くて、全く同一のクエリが頻繁に発行されるなら効く場合がある。テーブルへの更新処理が実行されるたびにキャッシュの内容はフラッシュされるので、相当読み出し処理が優位の場合でないと効果は期待できない。
実際にはデータの内容まで把握して管理できるアプリケーション側でmemcachedを使った方が、効果は高い。

InnoDB

安全のためにデータブロックを2回書いている処理を省略するオプション。予防のために書いているだけなので、省略しても問題ない。万が一のときにはマスタから復旧する前提で、スレーブでは有効にするのもいいのでは

  • innodb_flush_log_at_trx_commit=0

トランザクションをcommitしたときのディスクへの書き出し処理を省略するオプション。ただし毎秒のフラッシュは実行される。万が一のときにはマスタから復旧する前提で、スレーブでは有効にするのもいいのでは。
もちろんマスタではクラッシュ時に整合性が壊れる可能性があるので、やっちゃ駄目なオプション。

  • innodb_flush_method=O_DIRECT

OSのブロックバッファをバイパスして直接I/Oするオプション。これ自体はほとんど高速化に寄与しないが、メモリの二重利用を避けるという意味で効果がある。有効にするとOSのキャッシュから完全に外れるため、buffer_poolが不足していると覿面にI/Oが増加する。そのときはもちろんbuffer_poolを増やすべし。

MyISAM

  • delay_key_write=ALL

キーの遅延書き込みだけなので、データ本体への欠損は生じないはず。テーブルが閉じられるタイミングでディスクに書き出される。
クラッシュ時はそのときにオープンしていたテーブルのインデックスファイルが破損する可能性が高いので、全てのMyISAMテーブルに対してチェックを行う必要がある。