Introscope SQL Agent for Java の設定
内容
apmdevops96jp
内容
SQL エージェントの概要
SQL エージェントは、詳細なデータベース パフォーマンス データを Enterprise Manager にレポートします。 SQL エージェントは、管理対象アプリケーションとデータベース間のやり取りを追跡することによって、アプリケーションの個別の SQL ステートメントのパフォーマンスを詳しく調べることができます。
Java エージェントがアプリケーションを監視するのと同じように、SQL エージェントは SQL ステートメントを監視します。 SQL エージェントは目立たず、非常に低いオーバーヘッドでアプリケーションまたはデータベースを監視します。
個別の SQL ステートメント レベル単位までの有意義なパフォーマンス測定を行うために、SQL エージェントは収集するパフォーマンス データを要約します。これは、トランザクション固有のデータを除外し、元の SQL ステートメントを Introscope 固有の正規化されたステートメントに変換することによって実現します。 正規化されたステートメントには、クレジット カード番号などの機密情報が含まれないので、この処理でもデータのセキュリティは守られます。
たとえば、SQL エージェントが以下の SQL クエリを変換するとします。
SELECT * FROM BOOKS WHERE AUTHOR = 'Atwood'
以下は、変換後の正規化されたステートメントです。
SELECT * FROM BOOKS WHERE AUTHOR = ?
同様に、SQL エージェントが以下の SQL 更新ステートメントを変換するとします。
INSERT INTO BOOKS (AUTHOR, TITLE) VALUES ('Atwood', 'The Robber Bride')
以下は、変換後の正規化されたステートメントです。
INSERT INTO BOOKS (AUTHOR, TITLE) VALUES (?, ?)
注:
引用符内のテキスト('xyz')のみが正規化されます。正規化されたステートメントのメトリックは集約されます。
SQL エージェント ファイル
SQL エージェントは、すべてのエージェント インストールに含まれています。 SQL エージェント機能を提供するファイルは以下のとおりです。
- wily/core/ext/SQLAgent.jar
- wily/core/config/sqlagent.pbd
注:
デフォルトで、SQLAgent.jar ファイルなどのエージェントの拡張は、wily/core/ext ディレクトリにインストールされます。 エージェントの拡張ディレクトリの場所は、エージェント プロファイルの introscope.agent.extensions.directory プロパティで変更できます。 このプロパティの変更を有効にするには、管理対象アプリケーションを再起動する必要があります。/ext
ディレクトリの場所を変更する場合は、/ext
ディレクトリの内容も同様に移動する必要があります。SQL ステートメントの正規化
アプリケーションの中には非常に大量の独自の SQL ステートメントを生成してしまうものがあります。 EJB 3.0 のようなテクノロジが使用されている場合、長い独自の SQL ステートメントが増えてしまう可能性があります。 長い SQL ステートメントはエージェント内のメトリック増加の原因となり、他のシステム上の問題だけでなくパフォーマンスを低下させることになります。
不適切に記述された SQL ステートメントがメトリック増加を引き起こす仕組み
通常、SQL エージェント メトリックの数は、一意の SQL ステートメントの数とほぼ一致します。 アプリケーションで小規模な SQL ステートメント セットを使用しているにもかかわらず、一意の SQL メトリックが大規模かつ急激に増加していることが SQL エージェントによって示される場合は、SQL ステートメントの作成方法に問題がある可能性があります。
SQL ステートメントによってメトリックが急増するときには、次のように共通する状況がいくつかあります。
例: SQL ステートメントのコメント
SQL ステートメント内でのコメントの使用は、メトリックが急増する一般的な原因の 1 つです。 たとえば、以下のような SQL ステートメントがある場合、
"/* John Doe, user ID=?, txn=? */ select * from table..."
SQL エージェントは、以下のように、メトリック名の一部としてコメントを使用したメトリックを作成します。
"/* John Doe, user ID=?, txn=? */ select * from table..."
SQL ステートメントに埋め込まれているコメントは、誰がどのクエリを実行しているのかをデータベース管理者が確認するのに役立ちますが、クエリを実行しているデータベースはそのコメントを無視します。 一方で、SQL エージェントは、SQL ステートメントをキャプチャしても、そのコメント文字列を解析しません。 そのために、SQL エージェントは、一意なユーザ ID ごとに独自のメトリックを作成し、メトリック増加を引き起こす原因となります。
この問題は、SQL コメントを一重の引用符で囲むことで回避することができます。 たとえば、以下の通りです。
"/*' John Doe, user ID=?, txn=? '*/ select * from table..."
すると SQL エージェントは、以下のようなメトリックを作成し、コメントによって一意のメトリック名が作成されなくなります。
"/* ? */ select * from table..."
例: 一時表または自動的に生成された表名
メトリックが急増するその他の潜在的な原因は、一時表、または SQL ステートメントで自動的に生成された名前を持つ表を参照するアプリケーションである場合があります。 たとえば、Investigator を開いて Backends|{backendName}|SQL|{sqlType}|sql の下のメトリックを表示した場合、 以下のようなメトリックが表示される場合があります。
SELECT * FROM TMP_123981398210381920912 WHERE ROW_ID = ?
この SQL ステートメントは、表名に一意の識別子が追加されている一時表にアクセスしています。
TMP_
という表名に追加された数字によって、ステートメントが実行されるたびに一意のメトリック名が作成され、メトリックが急増します。例: 値のリストを生成する、または値を挿入するステートメント
メトリックが急増するその他の原因には、値のリストを生成するステートメント、または値を大量に変更するステートメントがあります。 たとえば、潜在的なメトリック増加に関する警告をすでに受け取っていて、調査の結果、以下の SQL ステートメントを見直す必要があると仮定します。
#1 INSERT INTO COMMENTS (COMMENT_ID, CARD_ID, CMMT_TYPE_ID, CMMT_STATUS_ID,CMMT_CATEGORY_ID, LOCATION_ID, CMMT_LIST_ID, COMMENTS_DSC, USER_ID,LAST_UPDATE_TS) VALUES (?, ?, ?, ?, ?, ?, ?, "CHANGE CITY FROM CARROLTON,TO CAROLTON, _ ", ?, CURRENT)
コードを調べてみると、
"CHANGE CITY FROM CARROLTON, TO CAROLTON, _ "
が都市名の配列を生成していることが分かります。同様に、潜在的なメトリックの急増を調査している場合は、これに似た SQL ステートメントを確認することをお勧めします。
CHANGE COUNTRY FROM US TO CA _ CHANGE EMAIL ADDRESS FROM TO BRIGGIN @ COM _ "
コードを調べてみると、CHANGE COUNTRY により国名が大量にリストされることがわかります。 また、国名に引用符を付けると、ユーザの電子メール アドレスが SQL ステートメントに挿入され、メトリックの急増の原因となり得る一意のメトリックが作成されます。
SQL ステートメントの正規化オプション
長い SQL ステートメントを解決するには、以下のような SQL エージェントに使用するノーマライザを含めます。
デフォルト SQL ステートメント ノーマライザ
SQL エージェントでは、デフォルトで標準 SQL ステートメント ノーマライザがオンになっています。 これは一重の引用符内のテキストを正規化します('xyz')。 たとえば、SQL エージェントが以下の SQL クエリを変換するとします。
SELECT * FROM BOOKS WHERE AUTHOR = 'Atwood'
以下は、変換後の正規化されたステートメントです。
SELECT * FROM BOOKS WHERE AUTHOR = ?
正規化されたステートメントのメトリックは集約され、Workstation の Investigator に表示することができます。
カスタム SQL ステートメント ノーマライザ
SQL エージェントでは、カスタムの正規化を実行するための拡張を追加できます。 これを行うため、SQL エージェントによって実装されている正規化スキーマを含む JAR ファイルを作成します。
SQL ステートメントのノーマライザ拡張を適用できます。
以下の手順に従います。
- 拡張 JAR ファイルを作成します。注:SQL ノーマライザ拡張ファイルのエントリ ポイント クラスは、com.wily.introscope.agent.trace.ISqlNormalizerインターフェースを実装している必要があります。JAR 拡張ファイルの作成には、SQL ノーマライザ拡張用の特定のキーを含むマニフェスト ファイルの作成が含まれます。これについては、以下の手順 2 で詳しく説明します。 ただし、拡張を動作させるためには、その他の一般キーも必要です。 これらのキーは、すべての拡張ファイルを作成するときに使用するタイプです。 作成する拡張ファイルは、データベース SQL ステートメント テキスト正規化、たとえばBackends|{backendName}|SQL|{sqlType}|{actualSQLStatement}ノードの下のメトリックと関連します。{actualSQLStatement}は、SQL ノーマライザによって正規化されます。
- 作成した拡張のマニフェストに、以下のキーを配置します。
- com-wily-Extension-Plugins-List:testNormalizer1注:このキーの値は任意です。 このインスタンスでは、例としてtestNormalizer1が使用されています。 このキーの値として指定するものはすべて、以下のキーでも同様に使用してください。
- com-wily-Extension-Plugin-testNormalizer1-Type: sqlnormalizer
- com-wily-Extension-Plugin-testNormalizer1-Version: 1
- com-wily-Extension-Plugin-testNormalizer1-Name: normalizer1ノーマライザの一意の名前を含んでいる必要があります。たとえば normalizer1 となります。
- com-wily-Extension-Plugin-testNormalizer1-Entry-Point-Class: <ISQLNormalizer 実装の完全修飾クラス名>
- 作成した拡張ファイルを<Agent_Home>/core/extディレクトリに配置します。
- IntroscopeAgent.profileで、以下のプロパティを配置および設定します。introscope.agent.sqlagent.normalizer.extension作成した拡張のマニフェスト ファイルからプロパティをcom-wily-Extension-Plugin-{plugin}-Nameに設定します。 このプロパティの値は大文字と小文字を区別しません。 たとえば、以下の通りです。introscope.agent.sqlagent.normalizer.extension=normalizer1重要:これはホット プロパティです。 拡張名を変更すると、拡張を再登録する必要があります。
- IntroscopeAgent.profileで、オプションで以下のプロパティを追加してエラー スロットル カウントを設定できます。introscope.agent.sqlagent.normalizer.extension.errorCount注:カスタム ノーマライザ拡張によってスローされたエラーがエラー スロットル カウントを超えたとき、拡張は無効となります。
- IntroscopeAgent.profileを保存します。
- アプリケーションを再起動します。
例外
作成した拡張によって、あるクエリに対してエラーが発生した場合、デフォルトの SQL ステートメント ノーマライザはそのクエリに対してデフォルトの正規化スキーマを使用します。 このようなことが発生した場合は、拡張によって例外が発生したことを示す ERROR メッセージが記録され、スタック トレース情報と一緒に DEBUG メッセージも記録されます。 ただし、このようなエラーが 5 個発生すると、デフォルトの SQL ステートメント ノーマライザは作成した拡張を無効にし、ノーマライザが変更されるまで今後のクエリで作成した拡張が使用されるのを停止します。
Null または空の文字列
クエリに対して、作成した拡張が Null 文字列または空の文字列を返す場合、StatementNormalizer はそのクエリに対してデフォルト正規化スキーマを使用し、拡張が Null 値を返したことを示す INFO メッセージが記録されます。 ただし、このような Null または空の文字列が 5 個返されると、StatementNormalizer はメッセージのログ記録を停止しますが、引き続き拡張の使用を試みます。
正規表現の SQL ステートメントのノーマライザ
SQL エージェントには、設定可能な正規表現(regex)に基づいて SQL ステートメントを正規化する拡張機能が用意されています。 この
RegexNormalizerExtension.jar
ファイルは <Agent_Home>/core/ext
ディレクトリにあります。正規表現拡張機能を適用できます。
以下の手順に従います。
- IntroscopeAgent.profileを開きます。
- 以下のプロパティで設定を行います。
- introscope.agent.sqlagent.normalizer.extension=RegexSqlNormalizer事前設定されているノーマライザ スキーマを上書きするのに使用される SQL ノーマライザ拡張機能の名前を指定します。 正規表現拡張機能を有効にする場合、このプロパティを RegexSqlNormalizer に設定します。
- introscope.agent.sqlagent.normalizer.regex.keys=key1このプロパティは、リストされた順番に評価される regex グループ キーを指定します。 正規表現拡張機能を有効化するためには、このプロパティが必要です。 デフォルトの値はありません。
- introscope.agent.sqlagent.normalizer.regex.key1.pattern=Aこのプロパティは、SQL ステートメントと照合するのに使用される regex パターンを指定します。java.util.Regexパッケージ クラスで許可されている有効な正規表現は、すべてここで使用可能です。 正規表現拡張機能を有効化するためには、このプロパティが必要です。 デフォルトの値はありません。
- introscope.agent.sqlagent.normalizer.regex.key1.replaceFormat=Bこのプロパティは、置換文字列の形式を指定します。java.util.Regexパッケージ クラスで許可されている有効な regex は、すべてここで使用可能です。 正規表現拡張機能を有効化するためには、このプロパティが必要です。 デフォルトの値はありません。
- introscope.agent.sqlagent.normalizer.regex.matchFallThrough=falseこのプロパティが true に設定されている場合、SQL 文字列はすべての regex キー グループに対して評価されます。 実装は連鎖されます。 したがって、SQL 文字列が複数のキー グループと一致する場合、group1 からの正規化された SQL 出力は group2 の入力となり、同じように続きます。プロパティが false に設定されている場合、キー グループが SQL 文字列と一致するとすぐに、そのグループから正規化された SQL 出力が返されます。 MatchFallThrough property によって拡張機能が有効化または無効化されることはありません。たとえば、Select * from A where B という SQL 文字列がある場合には、以下のようにプロパティを設定します。introscope.agent.sqlagent.normalizer.regex.keys=key1,key2introscope.agent.sqlagent.normalizer.regex.key1.pattern=Aintroscope.agent.sqlagent.normalizer.regex.key1.replaceFormat=Xintroscope.agent.sqlagent.normalizer.regex.key2.pattern=Bintroscope.agent.sqlagent.normalizer.regex.key2.replaceFormat=Y
introscope.agent.sqlagent.normalizer.regex.matchFallThroughがfalseの場合、SQL は key1 regex に対して正規化されます。 その regex からの出力は、Select * from X where Bとなります。この SQL が返されます。introscope.agent.sqlagent.normalizer.regex.matchFallThroughがtrueの場合、SQL は最初に key1 regex に対して正規化されます。 この regex からの出力は、Select * from X where Bです。次にこの出力は、key2 regexにフィードされます。Key2 regexからの出力はSelect * from X where Yです。これが返される SQL になります。注:正規表現拡張機能を有効化する場合、このプロパティは必要ありません。introscope.agent.sqlagent.normalizer.regex.key1.replaceAllがfalseの場合、SQL ステートメントは次のように正規化されます:Select * from X where A like Z。introscope.agent.sqlagent.normalizer.regex.key1.replaceAllがtrueの場合、SQL ステートメントは次のように正規化されます:Select * from X whereXlike Z。デフォルト値は false です。 正規表現拡張機能を有効化するために、このプロパティは必要ありません。注:いずれの正規表現パターンも入力 SQL と一致しない場合、RegexNormalizer は Null の文字列を返します。 ステートメント ノーマライザは次に、デフォルトの正規化スキーマを使用します。 - IntroscopeAgent.profileを保存します。
重要:
このトピックで記述されている上記のプロパティはすべてホット プロパティです。つまりこれらのプロパティに対する変更は IntroscopeAgent.profile
を保存した時点で有効になります。正規表現 SQL ステートメント ノーマライザの例
以下の 3 つの例は、正規表現 SQL ステートメント ノーマライザの実装方法を理解するのに役立ちます。
例 1
これは正規表現 SQL ステートメントを正規化する前の SQL クエリです。
INSERT INTO COMMENTS (COMMENT_ID, CARD_ID, CMMT_TYPE_ID,CMMT_STATUS_ID, CMMT_CATEGORY_ID, LOCATION_ID, CMMT_LIST_ID,COMMENTS_DSC, USER_ID, LAST_UPDATE_TS) VALUES(?, ?, ?, ?, ?, ?,?, ‘’CHANGE CITY FROM CARROLTON, TO CAROLTON, _ ", ?, CURRENT)
理想的な正規化された SQL ステートメントは以下のようになります。
INSERT INTO COMMENTS (COMMENT_ID, ...) VALUES (?, ?, ?, ?, ?, ?,?, CHANGE CITY FROM ( )
IntroscopeAgent.profile
ファイルを上記の正規化された SQL ステートメントにするために必要な設定は以下のとおりです。introscope.agent.sqlagent.normalizer.extension=RegexSqlNormalizerintroscope.agent.sqlagent.normalizer.regex.matchFallThrough=trueintroscope.agent.sqlagent.normalizer.regex.keys=key1,key2introscope.agent.sqlagent.normalizer.regex.key1.pattern=(INSERT INTOCOMMENTS \\(COMMENT_ID,)(.*)(VALUES.*)''(CHANGE CITY FROM \\().*(\\))introscope.agent.sqlagent.normalizer.regex.key1.replaceAll=falseintroscope.agent.sqlagent.normalizer.regex.key1.replaceFormat=$1 ...) $3$4 $5introscope.agent.sqlagent.normalizer.regex.key1.caseSensitive=falseintroscope.agent.sqlagent.normalizer.regex.key2.pattern='[a-zA-Z1-9]+'introscope.agent.sqlagent.normalizer.regex.key2.replaceAll=trueintroscope.agent.sqlagent.normalizer.regex.key2.replaceFormat=?introscope.agent.sqlagent.normalizer.regex.key2.caseSensitive=false
例 2
これは正規表現 SQL ステートメントを正規化する前の SQL クエリです。
SELECT * FROM TMP_123981398210381920912 WHERE ROW_ID =
理想的な正規化された SQL ステートメントは以下のようになります。
SELECT * FROM TMP_ WHERE ROW_ID =
IntroscopeAgent.profile
ファイルを上記の正規化された SQL ステートメントにするために必要な設定は以下のとおりです。introscope.agent.sqlagent.normalizer.extension=RegexSqlNormalizerintroscope.agent.sqlagent.normalizer.regex.matchFallThrough=trueintroscope.agent.sqlagent.normalizer.regex.keys=key1introscope.agent.sqlagent.normalizer.regex.key1.pattern=(TMP_)[1-9]*introscope.agent.sqlagent.normalizer.regex.key1.replaceAll=falseintroscope.agent.sqlagent.normalizer.regex.key1.replaceFormat=$1introscope.agent.sqlagent.normalizer.regex.key1.caseSensitive=false
例 3
SQL ステートメントを次のように正規化したいとします。
Select .... ResID1, CustID1
where ResID1=.. OR ResID2=.. n times OR CustID1=.. OR n times
のように正規化するには、プロパティを以下のように設定できます。introscope.agent.sqlagent.normalizer.regex.matchFallThrough=trueintroscope.agent.sqlagent.normalizer.regex.keys=default,defintroscope.agent.sqlagent.normalizer.regex.default.pattern=(ResID)[1-9]introscope.agent.sqlagent.normalizer.regex.default.replaceAll=trueintroscope.agent.sqlagent.normalizer.regex.default.replaceFormat=$1introscope.agent.sqlagent.normalizer.regex.default.caseSensitive=trueintroscope.agent.sqlagent.normalizer.regex.def.pattern=(CustID)[1-9]introscope.agent.sqlagent.normalizer.regex.def.replaceAll=trueintroscope.agent.sqlagent.normalizer.regex.def.replaceFormat=$1introscope.agent.sqlagent.normalizer.regex.def.caseSensitive=true
コマンドラインの SQL ステートメントのノーマライザ
正規表現 SQL ノーマライザが使用されておらず、where 句で値が二重引用符(" ")で囲まれている場合、以下のコマンドライン コマンドを使用して SQL ステートメントを正規化します。
-DSQLAgentNormalizeDoubleQuoteString=true
重要:
このコマンドの代わりに正規表現 SQL ノーマライザを使用して、二重引用符の SQL ステートメントを正規化することができます。 詳細については、「正規表現の SQL ステートメントのノーマライザ」を参照してください。ステートメント メトリックの無効化
アプリケーションの中には大量の独自の SQL ステートメントを生成するものがあり、その結果、SQL エージェントにおいてメトリックが爆発的に増加してしまう場合があります。 SQL エージェントの中で SQL ステートメント メトリックをオフにできます。
注:
ステートメント メトリックをオフにした場合でも、バックエンドまたはトップレベルの JDBC メトリックは失われません。以下の手順に従います。
- sqlagent.pbd ファイルを開き、SQL ステートメントを探します。 たとえば、以下の通りです。TraceOneMethodWithParametersIfFlagged: SQLAgentStatements executeQuery(Ljava/lang/String;)Ljava/sql/ResultSet; DbCommandTracer "Backends|{database}|SQL|{commandtype}|Query|{sql}"
- 無効化する追跡ディレクティブから{sql}を削除します。 たとえば、以下の通りです。TraceOneMethodWithParametersIfFlagged: SQLAgentStatements executeQuery(Ljava/ lang/String;)Ljava/sql/ResultSet; DbCommandTracer "Backends|{database}|SQL|{commandtype}|Query"
- sqlagent.pbdファイルを保存します。SQL エージェント内の SQL ステートメント メトリックがオフになりました。
SQL メトリック
SQL エージェントのメトリックは Introscope Workstation Investigator の[Backends]ノードの下に表示されます。 SQL ステートメント メトリックは、Backends|<バックエンド名>|SQL ノードの下に表示されます。
注:
[Average Response Time (ms)
]は、ExecuteReader()
メソッドを介して実行されたクエリなどのデータ リーダを返すクエリのみを表示します。 このメトリックは、データ リーダの Close()
メソッドにかかった平均時間を表します。SQL データに特有のメトリック タイプには以下のものがあります。
- 接続数 -- メモリ内の接続オブジェクトの数。 これらはオープン(ライブ)接続またはクローズ接続です。接続は、ドライバのconnect()メソッドが呼び出されると開始され、その接続がclose()メソッドで閉じられると終了します。 SQL エージェントは、接続への弱い参照をセットで保持します。 接続がガベージ コレクトされた場合、カウントには変更が反映されます。
- 平均結果処理時間(ミリ秒) -- クエリの平均処理時間。このメトリックは、executeQuery()呼び出しの最後から結果セットのclose()メソッドの呼び出しまでの、結果セットの処理にかかる平均時間を示します。
注:
インスツルメントされた XADataSource は、コミットまたはロールバック メトリックをレポートしない可能性があります。 ほかのインスツルメントされたデータソースは、メトリックにデータが含まれていない限り、コミットまたはロールバック メトリックをレポートしない可能性があります。