DB KPI取得のススメ

まずそもそもKPIってなんやねん、と。

Key Performance Indicator
業績管理評価のための重要な指標

KPIとは【Key Performance Indicator】(重要業績評価指標) - 意味/解説/説明/定義 : IT用語辞典

用語的な意味はこんなとこですが、ここではざっくり「DB性能評価指標」と考えてください。


うちの会社では定常的にMySQLから情報を吸いあげて、これを蓄積しつつ性能管理に役立てています。
これをDB KPI管理なんて呼んでいます。

著作権が怪しいのでソースを載せるのは控えますが、延々とshow statusの60秒間の平均を取るスクリプトをdaemontoolsで回し続けています。

取得対象はCom_[insert|delete|update|select]、Innodb_rows_% (うちはInnoDBばかりなので) あたりです。
累積値が取れるので、実行タイミングごとで差分を見てあげればいいですね。
mysqladmin extended-statusでもいいかと思います。

あとThreads_runningを「concurrency」として合わせて取得してます。
(これは累積値取ってもしょうがないので、1秒未満のとても短いサイクルで瞬間値を取って平均に丸めています。)


特にこのconcurrencyを重要視しています。

Threads_running、すなわちその時何かを実行中のthreadの数なので、これが異様に溜まっているとその時MySQLでは何かが起きているわけです。
詳しくは以下の論文が参考になるわけですが、この値がHWのCPU実コア数を超えると性能限界に達するのだ、と考えています。

Percona | Forecasting MySQL Scalability with the Universal Scalability Law
(難しい数式がたくさん出てきますが、途中に出てくるグラフを見たら言いたいことはわかります。)


なのでこのconcurrencyに対して適切な閾値を定めてあげて、それを超えてくるようならアラートを上げる、なんてしてあげるとスケールアウトの時期なんかが定量的に測れてしまうわけなのです。

もちろんこれは大前提として、洗練されたselectと適切な行数への更新が行われているDB上でのベンチマーク結果なので、実際はここまでの性能は出せないかもしれません。
経験則ですが12コア、メモリ60GBぐらいのサーバならトータル2-3万QPSは捌けるはずなので、これに満たない場合はクエリチューニングを頑張りましょう。


僕が作った仕組みじゃないですが、日々の業務にとっっっっっっっても役に立っています。
このデータを活かすとこんなことができてしまうわけです。

  • 一時的にslaveのレプリを止めて溜まった更新が追いつく時のスピードで更新qpsの限界値を見る
    • HWスペックとかそのDBの用途、クエリの性質ごとで数値は変わってくるのですが、そろそろ分割かなぁとかshard追加するかぁとかの目星がつけやすくなります。
    • QPSだけだとバルクインサートとか複数行updateがいると数字がやたら小さくなるので、そういう時はInnoDB_rows_XXXが参考になります。
  • ある特定の時間にconcurrencyが高まる
    • その時間に実行されるバッチに質の悪いクエリが潜んでいるかも!
    • long_query_timeを短くしてslow-logで炙りだす!
  • QPSは低いのにconcurrencyが高い
    • indexの効いていないクエリがいるかも・・・
      • tcpdump & pt-query-digestの出番です!
    • 実はやたらとlock wait timeoutしていたり・・・

などなど。


まだまだ活用の方法はあったりするんですが、ほんとに役に立つのでDBAな方は騙されたと思って仕組みを作ってみるとのちのちHappyになれると思いますよ!!