2015-12-10
MySQL関連のパラメータ(主にInnoDB)について
このエントリはMySQL Casual Advent Calendar 2015の10日目のエントリです。
先日のMySQL Casual Talks Vol8で@karupaneruraさんがパラメータの振り返りのような発表をされていたので、昨今あまり書かれなくなったMySQLに絡む設定パラメータについて書きます。それなりのメモリ(32GBとか)やSSDとか使ってる事を前提にしたような内容となります。
依存して変更した方が良いパラメータもあるので内容が前後に飛びますがご容赦下さい。またソースコードをがっつり読んだわけではなく、ベンチマーク中の挙動から推測している箇所が多分にあります。
結構突貫で書いているので後から微妙に修正する可能性があります。
InnoDBのパラメータ
- innodb_buffer_pool_size
- 挙げるまでも無く最近のバージョンのMySQLを使うなら必ず設定すべきパラメータ。データとINDEXが格納されるため、DB専用サーバとして使う場合は70%程度割り当てる事が推奨されます。後述する innodb_log_file_size やバイナリログはファイルシステムキャッシュにある程度載っていた方が良いのでギリギリまで攻める必要はないかと思います。
- innodb_page_sizeをデフォルト(16k)より小さくした場合、例えば4kにした場合は16kの時と比較し多くのメモリを消費するため、innodb_page_sizeを16kで運用していたサーバを4kに変更した場合は設定値によりますがGB単位で下げないとスワップ使い始めるため注意が必要です。
- innodb_log_file_size
- redoログを書くファイルのサイズ。所謂ib_logfileのファイルサイズを指定します。redoログの合計サイズはinnodb_log_file_size x innodb_log_files_in_group となるため数GBとする場合はinnodb_log_file_sizeを512MBとか1GBに設定し、innodb_log_files_in_groupを調整するのが良いと思います。1ファイルを大きくしすぎるとファイルシステムキャッシュから溢れやすくなるためです。更新が多い環境、かつ5.6以上を利用している場合は合計4GB以上に設定するのも有りです。5.5では合計の最大値が4GBのため注意して下さい。
- 一般にib_logfileの合計サイズが大きくなるとcrash recoveryの時間が長くなります。
- innodb_buffer_pool_instances
- innodb_flush_method
- innodb_purge_threads
- あまり意識している人はいない気がするパラメータ。5.6ではデフォルト1、5.7ではデフォルト4となっています。更新が多く、show engine innodb status\Gを見た場合に History list length [数字] の数字が肥大化していっている場合は増やす事が推奨されます。但しMySQLの再起動が必要です。History list lengthが増えているということはundo領域(デフォルトではibdata1と同居)が肥大化する要因となるため気を配ったほうが良いです。またHistory list lengthが大きくなっていくと基本的には性能が劣化する傾向があります。
- 何か時間の超絶かかるSELECTとかが実行されている場合もHistory list lengthが増える事があります。その場合は増やしてもたいした効果はないと考えられます(だってpurge出来ないし)
- なお、過去の記憶ですが、無駄に増やしすぎるとコンテキストスイッチが増加して少ない設定の時よりも性能が下がるので程ほどに設定して下さい。5.7なら殆どのケースでデフォルトで十分だと思います。
- innodb_io_capacity, innodb_io_capacity_max(max側は5.6から追加)
- I/O アクティビティー (バッファープールからのページのフラッシュや挿入バッファーからのデータのマージなど) に上限を設定します(めんどいのでマニュアルより)。
- 増やした方が良いケースとして知っているパターンを記載します。show engine innodb status\Gを実行し、INDIVIDUAL BUFFER POOL INFO以下の各バッファプールインスタンスのFree buffersが0で張り付いている場合は増やす事が推奨されます。少ないとバッファからのフラッシュ待ちが発生し性能劣化します。
- これはioリクエスト数ではなく、innodb_page_sizeを1としているように見受けられます。ですのでinnodb_page_sizeが16kと4kでは異なる設定にする事が推奨されます。1000設定していてinnodb_page_sizeが16kなら 16k x 1000だけ書こうとするはずです。
- このパラメータの挙動は5.5、5.6、5.7で全部微妙に違うはずなのでそれぞれの環境で調整する必要があります。5.7で改善され必要な状況では綺麗にpage/secで書込みを行うように見られました。5.7より前は設定値以上で書込みを行うケースが見受けられました。
- innodb_lru_scan_depth
- ざっくり書くとInnoDBバッファプールを使い切るぐらいのデータ・INDEXが存在する環境において各バッファプールインスタンスのFree buffersをどこまで空けておくかを指定します。デフォルト1024です。よってinnodb_buffer_pool_instancesがデフォルトの8の場合は1024 x 8(page)だけMySQLは空きを確保しようとします。
- innodb_lru_scan_depthの設定値を下回るとMySQLは空きを確保するために積極的にフラッシュしようとするようなので、innodb_io_capacityが少ないと待ち時間が長くなり性能劣化するようでした。
- 一般にinnodb_io_capacityを増やしたらinnodb_lru_scan_depthも増やせ、と言われているようです。但し、先にも記載したとおりバッファプールインスタンス毎になるためinnodb_buffer_pool_instancesの設定値も意識して調整する必要があります。
- innodb_checksum_algorithm
- innodb_change_buffer_max_size
- innodb_numa_interleave
- innodb_flush_neighbors, innodb_read_ahead_threshold
- innodb_read_io_threads, innodb_write_io_threads
- 変更して厳密に測定した事は無いのですが、SSDを使う場合は12とか設定した方が速くなる事が多いようです。
- innodb_adaptive_hash_index
その他のパラメータ
- thread_cache_size
- back_log
OS側色々
まとめ
色々と書いてみましたがどうでしょうか。一気に書き上げたので変な記載もあるかもしれませんが参考になれば幸いです。
個人的にはその他パラメータだとinnodb_adaptive_flushing_lwmを動かした場合の挙動をもうちょっとみたいと思っています。
他にもこの辺設定しろよ、とかあればMySQL CasualのSlackなんかでご連絡いただけると喜びます。
トラックバック - http://d.hatena.ne.jp/hiroi10/20151210/1449731029
リンク元
- 8 https://t.co/pZmcF1E5le
- 3 https://t.co/FL8FikQK6A
- 2 http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CEQQFjAF&url=http://goo.gl/mByvRr&ei=KyhpVtKNHPeewAPMFA&usg=AFQjCNG9OnTkRCbUk6wyJuKtWGr1enxX9w
- 2 https://www.google.co.jp/
- 1 http://qiita.com/
- 1 http://qiita.com/advent-calendar/2015/mysql-casual
- 1 http://qiita.com/drafts/d20a414f5298837cacd3
- 1 http://qiita.com/notona/items/c5a087d8dd446d315e6e
- 1 http://qiita.com/sasarkyz/followers
- 1 http://qiita.com/tbpgr/items/56eb65c0ea5882abbb07
おとなり日記
- 2015-12-07 あどけない話 4/27 14%