MySQL 初めてのチューニング

 2010/12/11 MySQL Casual Talks #1
          id:Craftworks
自己紹介
•   id:Craftworks
•   Twitter: @Craftworks
•   github: https://github.com/Craftworks
•   Blog: http://d.hatena.ne.jp/Craftworks
•   最近は EC2 で Perl 書いてます
•   ずっと PostgreSQL を使っていた MySQL
    初心者です
今日は MySQL をセットアップしてから
最初にするチューニングの話をします
MySQL のメモリ設定

MySQL のバッファタイプは2種類
 グローバルバッファ
  • mysqld 全体で確保するメモリ
 スレッドバッファ
  • コネクション毎に確保するメモリ
グローバルバッファ
innodb_buffer_pool_size
 – InnoDB のインデックスやレコードをキャッ
   シュする領域
 – InnoDB メインで使うなら最重要パラメータ
innodb_additional_mem_pool_size
 – InnoDB テーブル定義情報
 – 足りなくなったらエラーログに警告が出る
 – 足りなくなった時に増やせばよい
innodb_log_buffer_size
  – InnoDB トランザクションログを管理する領
    域
  – トランザクション終了時もしくは一定時間毎
    にディスクにフラッシュされる
  – 他のパラメータにメモリを回した方が得策
key_buffer_size
  – MyISAM のインデックスをキャッシュする領
    域
  – MyISAM をあまり使わないなら他に回す
query_cache_size
 – SELECT の実行結果をキャッシュする
 – パフォーマンス的にはかなり重要
 – query_cache_type でキャッシュ動作を指定
   できる
スレッドバッファ
sort_buffer_size
  – ORDER BY, GROUP BY に使われる領域
  – 多用する場合は増やす
read_rnd_buffer_size
  – ソート後にレコードを読む際に使用
  – ORDER BY の性能向上
join_buffer_size
  – インデックスを使用しないテーブル結合の
    際に使われる領域
  – インデックスを用いないテーブル結合は避
    けるべきなので大きくする必要は無い
read_buffer_size
  – テーブルスキャンのときに使われる領域
  – インデックスを使わないクエリは発行する
    べきではないので大きくする必要は無い
myisam_sort_buffer_size
 – MyISAM で DDL 系のクエリの時にインデッ
   クスのソートに使われる領域
 – 通常のクエリでは使われないのでそれほど
   多く取る必要は無い
メモリ以外の設定
innodb_log_file_size
  – InnoDBの更新ログを記録するディスク上の
    ファイル
  – innodb_log_file がいっぱいになったら、
    innodb_buffer_poolの中の更新されたデー
    タをディスクに書き出し
  – innodb_buffer_pool_size を大きくしたら
    innodb_log_file_size も合わせて調整
  – 大きくするほどクラッシュリカバリに時間が
    かかる
table_open_cache
 – 開いたテーブルのファイルポインタを格納
   する
 – 同時接続数×テーブル数が最低限必要
 – 1024〜2048 が一般的
 – MyISAM では1テーブルにつき2つ消費
 – OS が処理できる記述子数以内にする
   • cat /proc/sys/fs/file-max
thread_cache_size
 – スレッドをキャッシュして再接続のオーバー
   ヘッドを軽減する
 – 稼働状況に応じて設定する
 – コネクションプーリングしてる場合はあまり
   影響が無い?
以上を考慮して実際の設定
設定の目安
グローバルバッファ
 + (スレッドバッファ × 最大接続数)
 = 搭載メモリの 8 ~ 9 割
警告: 32-bit GNU/Linux x86 上では、メモリ使用を高く設定しすぎないように注意して
ください。glibc はプロセス ヒープがスレッド スタックよりも大きくなる事を許容する可
能性があり、その為サーバがクラッシュしてしまうかもしれません。もし次の式の値が
2GB に近い、またはそれを上回っていたら危険です:

innodb_buffer_pool_size + key_buffer_size +
max_connections*(sort_buffer_size+read_buffer_size+binlog_cache_size) +
max_connections*2MB
設定メモリ量の計算
• 個々の設定を計算するのは面倒臭い
 – ツールがあります
 – mymemcheck
 – !includedir に対応したものを github に置きました
 – https://gist.github.com/733390
 – mysql -e 'SHOW VARIABLES' | mymemcheck
 – mymemcheck ~/my.cnf
実行結果抜粋
global_buffers
 key_buffer_size                  16777216 16.000M
 innodb_buffer_pool_size         268435456 256.000M
 innodb_log_buffer_size           67108864 64.000M
 innodb_additional_mem_pool_size 20971520 20.000M
 net_buffer_length                   16384 16.000K
 ---------------------------------------------------
                                     total 356.016M
運用後のチューニング
key_buffer_size の調整
• SHOW STATUS LIKE 'Key_read%';
  – Key_read_requests / Key_reads = 150 以上になる
    ように key_buffer_size を調整
• SHOW STATUS LIKE 'Key_blocks%';
  – Key_blocks_unused が数百など少ない場合
    key_buffer_size を増やす必要がある。
最大接続数とスレッド数の確認
• SHOW STATUS LIKE '%connection%';
  – Max_used_connections
     • これまでに記録された同時接続数の最大値
• SHOW STATUS LIKE 'Threads%';
  – Threads_connected
     • 現在開いている接続の数
  – Threads_created
     • 接続を処理するために生成されたスレッド数
  – Threads_running
     • スリープ状態になっていないスレッド数
table_open_cache の調整
• SHOW STATUS LIKE 'Open_tables';
  – Open_tables
     • 現在開かれているテーブル数を確認
  – Opened_tables
     • たとえ多くの FLUSH TABLES を実行していない場合でも、
       この値が非常に大きい場合や急速に大きくなる場合
       は、テーブルキャッシュサイズを拡張する
query_cache_size の調整
• SHOW STATUS LIKE 'Qcache%';
  – Qcache_free_memory
     • query_cache_size で割り当てたメモリ残量
     • これが小さくなって、Qcache_lowmem_prunes が増加してい
       たら、query_cache_size の増量を検討
  – Qcache_inserts / Qcache_hits
     • Qcache_inserts に対して Qcache_hitsが少ないとキャッシュ
       のヒット率が悪い
  – Qcache_free_blocks
     • 増加している場合 → フラグメンテーション発生
        – FLUSH QUERY CACHE でデフラグする必要がある
クエリキャッシュの注意点


クエリキャッシュはケースセンシティブ
SELECT … と select … は別クエリ扱い
まとめ
• 最大限のパフォーマンスを発揮できるよ
  うに、なるべく多くのメモリを割り当てる
• かつ、コネクションが増えた時にメモリを
  食い過ぎてスワップが発生しないように、
  安全なラインに設定する
• 運用しながら SHOW STATUS で値を確認
  しながらチューニングする
参考
• 6.5.5. MySQL でのメモリの使用
   – http://dev.mysql.com/doc/refman/5.1/ja/memory-use.html
• 9.3. InnoDB スタートアップオプションとシステム変数
   – http://dev.mysql.com/doc/refman/5.1-olh/ja/innodb-parameters.html
• 4.13.3. クエリ キャッシュの設定
   – http://dev.mysql.com/doc/refman/5.1/ja/query-cache-configuration.html
• 6.4.8. MySQL でのテーブルのオープンとクローズの方法
   – http://dev.mysql.com/doc/refman/5.1/ja/table-cache.html
• 13.5.3. InnoDB 設定
   – http://dev.mysql.com/doc/refman/5.1/ja/innodb-configuration.html
• 5分でできる、MySQLのメモリ関係のチューニング!
   – http://dsas.blog.klab.org/archives/50860867.html
ご清聴ありがとうございました

MySQL 初めてのチューニング

  • 1.
    MySQL 初めてのチューニング 2010/12/11MySQL Casual Talks #1 id:Craftworks
  • 2.
    自己紹介 • id:Craftworks • Twitter: @Craftworks • github: https://github.com/Craftworks • Blog: http://d.hatena.ne.jp/Craftworks • 最近は EC2 で Perl 書いてます • ずっと PostgreSQL を使っていた MySQL 初心者です
  • 3.
  • 4.
    MySQL のメモリ設定 MySQL のバッファタイプは2種類 グローバルバッファ • mysqld 全体で確保するメモリ スレッドバッファ • コネクション毎に確保するメモリ
  • 5.
  • 6.
    innodb_buffer_pool_size – InnoDBのインデックスやレコードをキャッ シュする領域 – InnoDB メインで使うなら最重要パラメータ
  • 7.
    innodb_additional_mem_pool_size – InnoDBテーブル定義情報 – 足りなくなったらエラーログに警告が出る – 足りなくなった時に増やせばよい
  • 8.
    innodb_log_buffer_size –InnoDB トランザクションログを管理する領 域 – トランザクション終了時もしくは一定時間毎 にディスクにフラッシュされる – 他のパラメータにメモリを回した方が得策
  • 9.
    key_buffer_size –MyISAM のインデックスをキャッシュする領 域 – MyISAM をあまり使わないなら他に回す
  • 10.
    query_cache_size – SELECTの実行結果をキャッシュする – パフォーマンス的にはかなり重要 – query_cache_type でキャッシュ動作を指定 できる
  • 11.
  • 12.
    sort_buffer_size –ORDER BY, GROUP BY に使われる領域 – 多用する場合は増やす read_rnd_buffer_size – ソート後にレコードを読む際に使用 – ORDER BY の性能向上
  • 13.
    join_buffer_size –インデックスを使用しないテーブル結合の 際に使われる領域 – インデックスを用いないテーブル結合は避 けるべきなので大きくする必要は無い
  • 14.
    read_buffer_size –テーブルスキャンのときに使われる領域 – インデックスを使わないクエリは発行する べきではないので大きくする必要は無い
  • 15.
    myisam_sort_buffer_size – MyISAMで DDL 系のクエリの時にインデッ クスのソートに使われる領域 – 通常のクエリでは使われないのでそれほど 多く取る必要は無い
  • 16.
  • 17.
    innodb_log_file_size –InnoDBの更新ログを記録するディスク上の ファイル – innodb_log_file がいっぱいになったら、 innodb_buffer_poolの中の更新されたデー タをディスクに書き出し – innodb_buffer_pool_size を大きくしたら innodb_log_file_size も合わせて調整 – 大きくするほどクラッシュリカバリに時間が かかる
  • 18.
    table_open_cache – 開いたテーブルのファイルポインタを格納 する – 同時接続数×テーブル数が最低限必要 – 1024〜2048 が一般的 – MyISAM では1テーブルにつき2つ消費 – OS が処理できる記述子数以内にする • cat /proc/sys/fs/file-max
  • 19.
    thread_cache_size – スレッドをキャッシュして再接続のオーバー ヘッドを軽減する – 稼働状況に応じて設定する – コネクションプーリングしてる場合はあまり 影響が無い?
  • 20.
  • 21.
    設定の目安 グローバルバッファ + (スレッドバッファ× 最大接続数) = 搭載メモリの 8 ~ 9 割 警告: 32-bit GNU/Linux x86 上では、メモリ使用を高く設定しすぎないように注意して ください。glibc はプロセス ヒープがスレッド スタックよりも大きくなる事を許容する可 能性があり、その為サーバがクラッシュしてしまうかもしれません。もし次の式の値が 2GB に近い、またはそれを上回っていたら危険です: innodb_buffer_pool_size + key_buffer_size + max_connections*(sort_buffer_size+read_buffer_size+binlog_cache_size) + max_connections*2MB
  • 22.
    設定メモリ量の計算 • 個々の設定を計算するのは面倒臭い –ツールがあります – mymemcheck – !includedir に対応したものを github に置きました – https://gist.github.com/733390 – mysql -e 'SHOW VARIABLES' | mymemcheck – mymemcheck ~/my.cnf
  • 23.
    実行結果抜粋 global_buffers key_buffer_size 16777216 16.000M innodb_buffer_pool_size 268435456 256.000M innodb_log_buffer_size 67108864 64.000M innodb_additional_mem_pool_size 20971520 20.000M net_buffer_length 16384 16.000K --------------------------------------------------- total 356.016M
  • 24.
  • 25.
    key_buffer_size の調整 • SHOWSTATUS LIKE 'Key_read%'; – Key_read_requests / Key_reads = 150 以上になる ように key_buffer_size を調整 • SHOW STATUS LIKE 'Key_blocks%'; – Key_blocks_unused が数百など少ない場合 key_buffer_size を増やす必要がある。
  • 26.
    最大接続数とスレッド数の確認 • SHOW STATUSLIKE '%connection%'; – Max_used_connections • これまでに記録された同時接続数の最大値 • SHOW STATUS LIKE 'Threads%'; – Threads_connected • 現在開いている接続の数 – Threads_created • 接続を処理するために生成されたスレッド数 – Threads_running • スリープ状態になっていないスレッド数
  • 27.
    table_open_cache の調整 • SHOWSTATUS LIKE 'Open_tables'; – Open_tables • 現在開かれているテーブル数を確認 – Opened_tables • たとえ多くの FLUSH TABLES を実行していない場合でも、 この値が非常に大きい場合や急速に大きくなる場合 は、テーブルキャッシュサイズを拡張する
  • 28.
    query_cache_size の調整 • SHOWSTATUS LIKE 'Qcache%'; – Qcache_free_memory • query_cache_size で割り当てたメモリ残量 • これが小さくなって、Qcache_lowmem_prunes が増加してい たら、query_cache_size の増量を検討 – Qcache_inserts / Qcache_hits • Qcache_inserts に対して Qcache_hitsが少ないとキャッシュ のヒット率が悪い – Qcache_free_blocks • 増加している場合 → フラグメンテーション発生 – FLUSH QUERY CACHE でデフラグする必要がある
  • 29.
  • 30.
    まとめ • 最大限のパフォーマンスを発揮できるよ うに、なるべく多くのメモリを割り当てる • かつ、コネクションが増えた時にメモリを 食い過ぎてスワップが発生しないように、 安全なラインに設定する • 運用しながら SHOW STATUS で値を確認 しながらチューニングする
  • 31.
    参考 • 6.5.5. MySQLでのメモリの使用 – http://dev.mysql.com/doc/refman/5.1/ja/memory-use.html • 9.3. InnoDB スタートアップオプションとシステム変数 – http://dev.mysql.com/doc/refman/5.1-olh/ja/innodb-parameters.html • 4.13.3. クエリ キャッシュの設定 – http://dev.mysql.com/doc/refman/5.1/ja/query-cache-configuration.html • 6.4.8. MySQL でのテーブルのオープンとクローズの方法 – http://dev.mysql.com/doc/refman/5.1/ja/table-cache.html • 13.5.3. InnoDB 設定 – http://dev.mysql.com/doc/refman/5.1/ja/innodb-configuration.html • 5分でできる、MySQLのメモリ関係のチューニング! – http://dsas.blog.klab.org/archives/50860867.html
  • 32.