読者です 読者をやめる 読者になる 読者になる

mk(pt)-query-digestをもっと活用しよう!

もはやこれが無くては障害対応ができないぐらい中毒になっているmk-query-digestさんについてです。
mk-query-digest - Analyze query execution logs and generate a query report, filter, replay, or transform queries for MySQL, PostgreSQL, memcached, and more.

例えばこんなことが起きたときは、何を差し置いてもまずtcpdumpを取りに行きます。
状況がおさまってしまってからでは遅いのです。

  • Load Averageの高騰
  • Too Many Connections
  • lock wait timeout
tcpdump -i bond0 -s 65535 -x -n -q -tttt 'port 3306' > tcpdump.out 2> /dev/null

ここで素直に

mk-query-digest --type=tcpdump tcpdump.out > tcpdump.log

だけでは何とも勿体ない。
もちろんこれでもとても有意義な情報がとれてしまうわけですが、せっかく色々オプションがあるので試してみてはどうでしょう。

  • テーブルごとのアクセス集計
    • 垂直分割を検討している時や、アクセスが集中しているテーブルを割り出す時なんかに使います
    • order-byとlimitはお好きな値でどうぞ
mk-query-digest --type=tcpdump --group-by=tables --order-by Query_time:cnt --limit 100 tcpdump.out > tcpdump.log.pertable
  • 特定のクエリのみ集計
    • 正規表現部分をイジれば更新クエリだけの抽出もできちゃいます
mk-query-digest --type=tcpdump --filter '$event->{fingerprint} =~ m/^select/'  --order-by Query_time:cnt --limit 100 tcpdump.out > tcpdump.log
  • commit / ping / connect を除いて集計
    • ノイズになるものを除外!
mk-query-digest --type=tcpdump --filter '$event->{fingerprint} !~ m/^(commit|admin|set)/' --limit 100 tcpdump.out > tcpdump.log
  • 接続にかかった時間だけを抽出
mk-query-digest --type tcpdump --no-report --filter '$event->{fingerprint} =~ /Connect/ && printf "%.9f %s %s@%s\n", @{$event}{qw(Query_time host user db)}'
  • 特定のテーブルだけをテーブルごとに集計
    • もうある程度のあたりは付いてる時なんかに。
mk-query-digest --type=tcpdump --group-by=tables --order-by Query_time:cnt --limit 100  --filter 'grep /XXX/, @{$event->{tables}}' tcpdump.out > tcpdump.log.pertable

こうして取れた情報をshow create tableやらshow index、explainと組み合わせて、日々クエリのチューニングを行ったりしています。
qpsがとんでもなく高いDBでtcpdumpをカジュアルに打って放っておくとtoo many connectionsがドバドバ。。。なんてこともあるので目を離してはいけません。
2-3万qpsとかのサーバで10秒も打ったらサイズは150MBぐらい行っちゃいます。

僕がよく使うのはこの辺ですが、他にもたくさんの使い方があると思います。
みなさんの参考になれば幸いです。