BLOGTIMES
2004/11/03

cles::blogのチューニング

  mysql  tuning 
このエントリーをはてなブックマークに追加

さすがに昨日の一件には参ってしまったのですが、最近MySQLの負荷が高すぎることは確かなので少しチューニングをしてみることにしました。

その昔、Oracleバリバリだったときにはチューニングばかり勉強したりしていた時期もあったので、チューニングで何をしなければならないかというのは大体わかっているつもりです。今回はそのときの経験を生かして、MySQLのチューニングに挑戦してみます。

まずはボトルネック解析から

まずはなぜ遅いのかという原因を絞り込みます。これはDBのチューニングに限らず全てのチューニングという作業に共通したものですよね。これをやらずにチューニングやリソースの増強を行なうのは愚の骨頂です。

さて、遅いという現象は基本的に何らかのリソース不足なわけなので、どんなリソースがDBにとって不足しているのかということを調べることになります。

原因は大きく分けて以下の5つでしょうか。
 ・CPU
 ・メモリ
 ・ディスク
 ・ネットワーク
 (・リソースの競合[デッドロック])

これらの見分け方なんですが、OSがUNIX系の場合にはsarとかvmstatとかiostatとかfreeのようなコマンドを使うと比較的簡単にわかります*1

今回の症状は明らかにCPUネックでした。

パラメータをいじってみる

リソースを増強するのは最終手段なので、まずはタダでできるパラメータをいじるということから始めます。MySQLの場合、パラメータはmy.cnf*2に書くことができます。この件でいろいろ調べてわかったのですが、バージョンがあがるたびにパラメータも少しずつ増えているようです。

Oracleなんかだと公式非公式*3を含めてかなりチューニング方法がありますが、MySQLのチューニングっていうのはあまり聞きません。もともとデフォルトでそこそこのパフォーマンスを出してくれるということと、いじれるパラメータが少ない*4ことが関係しているのだと思います。

実践ハイパフォーマンスMySQL

とりあえずMySQLのチューニングについては公式マニュアルの「5 MySQL の最適化」に基本的なことは載っているので、このあたりのドキュメントを読めば基本的なことはつかめると思います。

遅いクエリを特定して、改善する

ボトルネック解析でCPUネックになっていることがわかったので、次にやることは時間のかかるQueryを特定することです。具体的にはmy.cnfに以下の行を追加することにより、実行に時間がかかっているQueryを特定してみました。

実行に5秒以上かかるQueryを(DATA_DIR)/slow.logに記録する

long_query_time=5
log-slow-queries=slow.log

しばらくサイトを立ち上げておくと、いくつかの怪しいクエリがlogに吐き出されていましたので、このクエリと、クエリが使っているテーブルに問題がないかを確認します。

確認したのはこの3点
 ・テーブルに適切なINDEXが設定されているか
 ・Where節にINDEXを使わせないような条件を指定していないか*5
 ・実行時にINDEXが適切に使用されているか

この確認はSQLにEXPLAINを付加してみることで*6簡単に確認できます。この部分の修正で、速度が3割ほどアップしました。

さらにクエリキャッシュを有効にしてみる

これでもまだ遅いので、MySQLのパラメータの設定情況を確認してみます。パラメータの確認はmysqladminを使って確認します。

mysqladmin variables

これで確認してみたところquery_cache_size0になっていることが判明しました。

6.9. MySQL クエリキャッシュ

(一部の)テーブルがそれほど頻繁には変更されず、同じクエリが何度も実行される環境では、クエリキャッシュが非常に役立ちます。 動的コンテンツを大量に持つ多くの Web サーバでは、このような状況が一般的です。

実行コストが高いクエリであっても、結果をキャッシュすることで負荷は劇的に改善するはずということで、下記の内容をmy.cnfに追加してみました。

query_cache_limit=1M
query_cache_min_res_unit=4k
query_cache_size=32M
query_cache_type=1

これの効果は絶大で、これまで10秒以上かかっていたクエリがコンマ数秒で実行できるようになりました。CPU負荷も許容範囲内に収まっています。

まぁ、キャッシュされているんですからCPU使ってなくて当たり前ですね。

ケチケチしないでもっとメモリを割り当ててあげればいいのかもしれないのですが、query_cache_sizeの値は様子を見ながら必要に応じて大きくしていきたいと思います。

とりあえず、今回はこれで一件落着

MySQLクックブック〈VOLUME1〉MySQLクックブック〈VOLUME2〉MySQL全機能リファレンス

  • *1: これらのコマンドは呪文のような数値をたくさん出力するのですが、各数値の意味がわかれば答えもおのずとわかります。
  • *2: Windowsの場合はmy.ini
  • *3: 通常の手段では入手できない隠しパラメータとかあったりします。
  • *4: いい意味で使っています。Oracleのパラメータ設定についてはノーコメントで。
  • *5: 具体的には式の評価順序や、Where節で計算式を使っていなかいどうかなどです。
  • *6: 別件ですが、Explainの例はこちらにあります。

トラックバックについて
Trackback URL:
お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/473
Trackbacks
phpMyAdminでMySQLを操作していると、なんか動作が異常に遅いと思うときがある。 データ数が数十万件あるテーブルだし、管理者の操作だから仕方が...
浜村拓夫の世界 (2009/09/24 17:05)
くだらんたわごとばかり続いていましたが、久々にサーバネタです。 最近表示されるまでもたもたする感じが出てきてます。エントリ数とアクセス数が増えているせいかも知れません。サーバの入れ替えはおっくう...
おやじまんのだめだこりゃ日記 (2006/04/13 00:12)
Local Trackbacks
MySQLのチューニングをしていて、ふとblog.bulknews.netのmiyagawaさんがMySQLのチューニング本を紹介していたことを思い出しました。 鉄は熱いうちに打てということで、出かけたついでに早速買ってきてみまし...
(2004-11-03)
Comments
愛のあるツッコミをお気軽にどうぞ。[policy]
古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
jojo (2004/12/17 18:02) <%HatenaAuth()%>

テストしていない無責任な質問なので
スルーされてもかまいませんが
query_cache_sizeを増やすと
結果をキャッシュするのでリアルタイムな結果や
掲示板などでの使用の場合やばくないですか?
定数値を格納してあるならば効果は絶大ですが。

hsur (2004/12/18 00:06) <%HatenaAuth()%>

マニュアルのクエリキャッシュの欄を読むとわかりますが、元データが更新されるとキャッシュは破棄されますので、メモリに余裕があれば特に問題ないと思います。現にウチでは全く問題なく動いていますよ。
http://dev.mysql.com/doc/my...

Comments Form

コメントは承認後の表示となります。
OpenIDでログインすると、即時に公開されます。

OpenID を使ってログインすることができます。

Identity URL: Yahoo! JAPAN IDでログイン