JmeterでDB負荷テストをやってみよう! | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

以前に「負荷テストあれこれ-JMeterの使い方- 」という記事を書いたのですが、こちらは主にWebアプリのフロントエンドから負荷をかけてシステムの全体性能をテストするというものでした。

今回のやり方は、バックエンド側のDBを中心に負荷テストをするやり方です。


前回のやり方でシステムの全体性能というものをある程度、把握することはできます。
ただ、DBなど特定の機能を持つシステムモジュールに対して負荷テストを実施してみたいという要望もあると思います。
DBに付属のツールを使えば、SQLの実行プランやその際の処理時間を計測したりすることもできます。
しかし、そういうのはSQL単体での話で、断続的に負荷をかけ続けた場合など、サーバーの性能を含めた負荷テストというのは実施ができません。


Jmeterには、JDBC経由でSQLを発行する機能が備わっており、前回の記事で書いた負荷テストのやり方同様に細かな制御でテストを実施することができます。
なお、ここでは2009年1月時点で最新のJmeter2.3.2のバージョンをベースに書いています。



JDBCドライバを用意する


JmeterでDBの負荷テストをする場合、JDBCドライバを用意しておく必要があります。
例えば、PostgreSQLへの負荷テストをしたい場合、PostgreSQLのJDBCドライバ をJmeterの環境に組み込んでおきましょう。


JDBCドライバは、Jmeterのインストールフォルダのlib/extフォルダにコピーしておきます。


A Day In The Boy’s Life-Jmeter-1



テストシナリオを作成する


Jmeterを起動した後にまずやることは、負荷テストのシナリオを作成することです。
Jmeter上の様々な機能を組み合わせることで、多様なテストシナリオを作り出すことが可能です。

DBの負荷テストに必要な機能は4つあります。
とりあえず、この4つの機能をJmeter起動後のテスト計画に追加しましょう。


1. スレッドグループ


全体の負荷を調整する機能です。
負荷テストあれこれ-JMeter 負荷のかけ方、レポートの見方- 」の中で書いたように、負荷のレベルの調整方法はDBの場合でも同じです。
「テスト計画」を右クリックして、「追加」→「スレッドグループ」から追加します。


2. JDBC Connection Configuration


DBの接続先や、コネクションプールの設定などが行えます。
詳細な設定方法は、後述の「」に記載しています。
「テスト計画」を右クリックして、「追加」→「設定エレメント」→「JDBC Connection Configuration」から追加します。


3. JDBC Request


発行するSQL文を記載します。
1つのJDBC Requestに対して1SQLとなります。
複数のSQLを使って負荷テストをしたい場合は、複数のJDBC Requestを追加します。
「テスト計画」を右クリックして、「追加」→「サンプラー」→「JDBC Request」から追加します。


4. リスナー


テスト結果をレポートにまとめるための機能です。
色々な種類のレポートがあるので、見たい形式のものを適宜追加しておくとよいでしょう。

個人的なお勧めとしては、全体感を把握するための「グラフ表示」、エラーが起きたときに応答データからその詳細を見ることができる「結果をツリーで表示」、コンパクトにレポートをまとめてくれる「統計レポート」です。
ただ、リスナーは追加すればするほど、負荷テストを実行するクライアント側にも負荷がかかるので、最終的には本当に必要なものだけしか残さないようにしておいたほうがよいでしょう。


追加した感じは、このようになります。


A Day In The Boy’s Life-Jmeterテスト計画



接続情報を入力する


DBへの接続情報は「JDBC Connection Configuration」の「Database Connection Configuration」から設定できます。


Database URL

DBへの接続パスです。

例) DBがPostgreSQLであった場合

jdbc:postgresql://192.168.0.100:5432/testdb

最後に指定しているのはDB名です。

JDBC Driver class 使用するJDBCドライバの情報を入力します。同じくPostgreSQLの場合「org.postgresql.Driver」のように指定します。
Username DBに接続する際のユーザー名です。
Password 上記ユーザーのパスワードです。

この辺りは、事前にJmeterを実行するクライアントPCからDBへの接続が正常に行えるのかを確認しておく必要があります。
PostgreSQLの場合、デフォルトだとN/W越しの接続はできませんので、事前に設定を変えておく必要があったりします。


参考: PostgreSQL8 外部からのアクセス制御あれこれ。


もう1つ「JDBC Connection Configuration」の中で設定しておく必要があるのが「Variable Name Bound to Pool」です。
この「Variable Name」欄に適当な変数名を入れておきましょう。
これは、SQL文を書くためのJDBC Requestの中にも存在します。
両者の変数名は同じものを指定しておく必要があります。


A Day In The Boy’s Life-Jmeter接続情報



実行するSQLを書く


続いて、実行したいSQLを書きます。
SQL文はシナリオ登録の際に追加した「JDBC Request」の中に記載します。

SELECT文を書いた場合は、「Query Type」を「Select Statement」に、UPDATEやINSERT文であれば「Update Statement」を選択しておきます。


A Day In The Boy’s Life-JmeterSQL文


また、前述したようにVariable Name Bound to Poolに書く変数名は、JDBC Connection Configurationの中で指定したものと同じ変数名を指定します。

複数のSQL文をシナリオに組み込みたい場合は、その数だけJDBC Requestを追加しておきます。(実行順序はスレッドグループの上からとなります)



負荷レベルを調整する


最後にやることはテストの負荷レベルの調整です。
負荷レベルは、スレッドグループで設定できるパラメータ「Ramp-Up期間」「スレッド数」「ループ回数」で調整できます。


A Day In The Boy’s Life-Jmeterスレッドプロパティ


この図では、6秒で2つのスレッドを実行させ合計60秒間の負荷テストを実施しています。


「Ramp-Up期間」「スレッド数」「ループ回数」の関係については、「負荷テストあれこれ-JMeter 負荷のかけ方、レポートの見方- 」に詳細を書いていますので、参照してください。


続いて、「JDBC Connection Configuration」の残りの部分を調整します。
ここには、コネクションプーリングの設定や最大接続数、自動コミットするかなどの設定があり、設定の仕方によってはパフォーマンスに影響がでてくるものがあります。
実際のアプリケーションの要件などを含めて、SQLごとに自動コミットさせるのか、特定の実行回数でコミットするのか、コネクションプーリングの有無など考慮して調整してみるとよいと思います。


ちなみに、特定回数SQLを実行した後にコミットさせるというテストシナリオですが、下記のようにすれば(無理やり)できたりします。


1. JDBC Connection ConfigurationのAuto CommitをFalseに設定


2. スレッドグループにループコントローラを追加し、その下にUpdate/Insert文を書いたJDBC Requestを追加する


3. JDBC Requestをスレッドグループの直下に追加して、Query TypeからCommitを選択しておく


こんなイメージです。


A Day In The Boy’s Life-Jmeterテストシナリオ2


例えば、スレッドグループ内で


スレッド数:10
Ramp-Up期間: 30
ループ回数: 1


としておき、ループコントローラにてループ回数を5としておきます。
すると3秒に1度スレッドが実行されますが、1つのスレッドの中で5回ループされますので、Update/Insert文が5回実行されます。

5回実行されるとループから抜けて、Commitを定義したJDBC Requestが呼び出されCommitされるという具合です。
合計で、50回のUpdate/Insert文、10回のCommit(3秒おきに)が実行されることとなります。



Jmeter利用時のエラー対処


Jmeterを利用している際に出たエラーとその対処方法です。
エラーの内容は、リスナーの「結果をツリーで表示」の中で見れる「Sampler result」の内容になります。


1. JDBCドライバが見つからなかった場合に出たエラー


Response message: java.sql.SQLException: No suitable driver found for jdbc:postgresql://192.168.0.100:5432/testdb

JDBCドライバを適切なところにおかず、テストを実行した際に出たエラーです。
JDBCドライバを用意する」のところで書いたように、適切なJDBCドライバを用意し、Jmeterのフォルダに格納しておきます。



2. 接続経路が間違っていた場合に出たエラー


Response message: org.postgresql.util.PSQLException: Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.

ホスト名(またはIP)やポート番号などが間違っていた場合に出たエラーです。
「JDBC Connection Configuration」内の「Database Connection Configuration」の内容を確認してみましょう。



3. DB上で、適切な権限が無かったときのエラー


Response message: org.postgresql.util.PSQLException: ERROR: permission denied for relation master

これはJmeterのエラーではないですね。
設定した接続ユーザーに対して適切な権限が与えられていなかったため発生したエラーです。



4. Variable Name Bound to Pool変数が適切に設定されていなかったときのエラー


Response message: java.sql.SQLException: No pool found named: ''

「JDBC Connection Configuration」と「JDBC Request」の中で設定する「Variable Name Bound to Pool」の変数名を入力していなかった、または変数名が異なっている場合に発生したエラーです。
両方を同じ変数名に設定することで回避できました。



5. Query Typeが違っていたときのエラー


Response message: org.postgresql.util.PSQLException: No results were returned by the query.

「JDBC Request」で書いたSQLに対してQuery Typeが適切でなかった場合に出たエラーです。
SELECT文を書いた場合は、「Query Type」を「Select Statement」に、UPDATEやINSERT文であれば「Update Statement」を選択しておきます。