WebSphere Message Broker バージョン 8.0.0.5 オペレーティング・システム: AIX、HP-Itanium、Linux、Solaris、Windows、z/OS

製品の最新バージョンについては、IBM Integration Bus バージョン 9.0 をご覧ください。

ESQL コードのヒント

ESQL で最適化手法をいくつか使用して、メッセージ・フローのパフォーマンスを改善させることができます。

始める前に:

ESQL コードを作成する際に、メッセージ・フローのパフォーマンスを改善するために使用できるいくつかの手法があります。 以下のセクションには、ESQL コードのパフォーマンスを改善させる方法についてのガイドが含まれています。

ESQL 配列処理

実行時に添え字が動的に評価される方法のために、配列添え字 [ ] はパフォーマンスの点で高コストです。 できる限り配列添え字の使用を避けることで、ESQL コードのパフォーマンスが改善される可能性があります。 代わりに参照変数を使用できます。その場合、配列へのポインターが保持され、後で再使用することができます。以下に例を示します。

DECLARE myref REFERENCE TO InputRoot.XML.Invoice.Purchases.Item[1];
-- Continue processing for each item in the array
WHILE LASTMOVE(myref)=TRUE DO
   -- Add 1 to each item in the array
   SET myref = myref + 1;
   -- Do some processing
   -- Move the dynamic reference to the next item in the array
   MOVE myref NEXTSIBLING;
END WHILE;

ESQL 配列処理の例:

以下の例に示す ESQL は、データベースから読み取られるレコードを処理するために使用されます。 Environment.Variables.DBData[A] のような配列添え字を繰り返して使用すると、処理時間が大幅に増加します。

SET Environment.Variables.DBDATA[] =
(
SELECT T.*
FROM Database.{'ABC'}.{'XYZ'} as T
);

DECLARE A INTEGER 1;
DECLARE B INTEGER CARDINALITY(Environment.Variables.*[]);
SET JPcntFODS = B;
WHILE A <= B DO
            CALL CopyMessageHeaders();
            CREATE FIELD OutputRoot.XML.FODS;
            DECLARE outRootRef REFERENCE TO OutputRoot.XML.Data;

            SET outRootRef.Field1 = Trim(Environment.Variables.DBDATA[A].Field1);
            SET outRootRef.Field2 = Trim(Environment.Variables.DBDATA[A].Field2);
            SET outRootRef.Field3 = Trim(Environment.Variables.DBDATA[A].Field3);
            SET outRootRef.Field4 = Trim(Environment.Variables.DBDATA[A].Field4);
            SET outRootRef.Field5 = Trim(Environment.Variables.DBDATA[A].Field5);
            . . .
            . . .
            SET outRootRef.Field37 = CAST(Environment.Variables.DBDATA[A].Field37)

            SET A = A + 1;
            PROPAGATE;
END WHILE;

参照変数を使用することで、処理時間を大幅に減らすことができます。

ESQL CARDINALITY 関数

ループの中では CARDINALITY の使用を避けてください。以下に例を示します。
WHILE ( I < CARDINALITY (InputRoot.MRM.A.B.C[]
ループが全探索されるたびに CARDINALITY 関数を評価する必要があり、パフォーマンス上のコストが大きくなります。 ループが頻繁に繰り返される大きな配列では、これは特に顕著です。 一度のみ評価されるようにするために、WHILE ループの前で配列のサイズを決定するほうが効率的です (ただし、サイズがループの中で変化する場合を除く)。以下に例を示します。
SET ARRAY_SIZE = CARDINALITY (InputRoot.MRM.A.B.C[]
WHILE ( I < ARRAY_SIZE )

ESQL DECLARE ステートメントおよび EVAL ステートメント

1 つのステートメントの中で変数を宣言して初期値を設定することにより、DECLARE ステートメントの数 (およびパフォーマンス・コスト) を減らすことができます。 あるいは、複数のステートメントではなく 1 つの ESQL ステートメントの中で同じデータ型の複数の変数を宣言することもできます。 この手法はメモリー使用量を削減するうえでも役立ちます。

相関名を動的に決定する必要がある場合には、EVAL ステートメントが使われることがあります。 ただしステートメントが 2 回実行されるため、CPU 使用量の点では高コストです。 最初の実行では、実行予定のステートメントを作成するためにコンポーネントの各部が決定されます。その後、作成されたステートメントが実行されます。

ESQL PASSTHRU ステートメント

PASSTHRU ステートメントを使用する場合、以下の手法によってパフォーマンスが大きく改善される可能性があります。

  • ストアード・プロシージャーを呼び出すために CALL ステートメントと共に PASSTHRU ステートメントを使用することを避けます。 代わりに、CREATE PROCEDURE ... EXTERNAL ... コマンドと CALL ... コマンドを使用できます。
  • リテラル値またはデータ値を必要とする SQL ステートメントを扱うときには、列値を変数にマップするホスト変数を使用します。 これにより、データベース内で動的 SQL ステートメントを再使用することができます。 動的ステートメントでの SQL PREPARE はパフォーマンスの点でコストの大きい操作であるため、これを一度だけ実行し、その後でステートメントを繰り返し EXECUTE する方が、PREPARE と EXECUTE を毎回行うよりも効率的です。

例えば、以下のステートメントにはデータ値とリテラル値が 2 つあります (100 および IBM)。

PASSTHRU(’UPDATE SHAREPRICES AS SP SET Price = 100 WHERE SP.COMPANY = ‘IBM’’);

このステートメントは、価格が 100 で会社が IBM である場合には効率的です。 Price または Company のどちらかが変更になった場合、別のステートメント (および別の SQL PREPARE ステートメント) が必要になり、パフォーマンスが影響を受けます。

しかし、以下のステートメントを使用した場合、PriceCompany が変化しても別のステートメント (別の PREPARE) は必要ありません。
PASSTHRU(’UPDATE SHAREPRICES AS SP SET Price = ? WHERE SP.COMPANY = ?’,
InputRoot.XML.Message.Price,InputRoot.XML.Message.Company);
動的 SQL でステートメントが最大限に再使用されていることを確認するために、以下のコマンドを使用して、DB2® の SQL ステートメント・キャッシュの内容を表示します。
db2 connect to <database name>
db2 get snapshot for database on <database name>
動的ステートメント・キャッシュの内容を表示するには、以下のコマンドを使用します。
db2 connect to <database name>
db2 get snapshot for dynamic SQL on <database name>

ESQL 参照変数

参照変数を使用すると、InputRoot.XMLNSC.A.B.C.D.E などの長い相関名を参照できます。以下の例に示されているように、参照ポインターを宣言します。
DECLARE refPtr REFERENCE to InputRoot.XMLNSC.A.B.C.D;

メッセージ・ツリーのエレメント E にアクセスするには、相関名 refPtr.E を使用します。

REFERENCE ステートメントおよび MOVE ステートメントを使用するとメッセージ・ツリー内のナビゲーションの量を減らすことができ、パフォーマンスが改善されます。 この手法は、多数の SET ステートメントまたは CREATE ステートメントを構築する場合に役立つ可能性があります。ツリー内の同じブランチまでナビゲートする代わりに、REFERENCE 変数を使ってブランチへのポインターを設定した後、MOVE ステートメントを使って一度に 1 つのフィールドを処理できます。

ESQL ストリング関数

ESQL 内で使われるストリング処理関数は CPU を集中的に使用する可能性があります。LENGTH、SUBSTRING、RTRIM などの関数はメッセージ・ツリー内の個々のバイトにアクセスする必要があります。 これらの関数はパフォーマンスの点で高コストであるため、その使用を最小限に抑えるとパフォーマンス改善に役立つ可能性があります。 また、可能であれば、中間結果を変数に保管することで、同じ連結を繰り返し実行することを避けてください。

反復レコードを含むメッセージ・ツリー

以下の状況ではパフォーマンスが低下する可能性があります。

  • 大規模なメッセージ・ツリーを取り扱うために ESQL 処理を使用している
  • メッセージ・ツリーが反復レコードや多数のフィールドによって構成されている
  • フィールドのアクセスまたは作成に、フィールド参照パスのある明示的な SET ステートメントを使用した
  • ESQL がより多くのフィールドまたは繰り返しを処理するにつれて、徐々にメッセージ・フローの処理が遅くなった

この問題は、連続するフィールドまたはレコードのアクセスまたは作成を行うために、参照変数ではなくフィールド参照を使用した場合に発生します。

以下の例に示す独立した SET ステートメントは、フィールド参照パスを使ってメッセージ・ツリーを操作します。 SET ステートメントのパラメーターは、ソースおよびターゲットで、いずれかまたは両方のパラメーターがフィールド参照です。

SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field = '1';

次の例に示すように、SET ステートメントを使ってさらに多数のフィールドを作成する場合、パフォーマンスが影響を受けます。

SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field1 = '1';
SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field2 = '2';
SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field3 = '3';
SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field4 = '4';
SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field5 = '5';

この例では、作成された 5 つのフィールドは、すべて ParentA の子です。 指定したフィールドを作成または変更する前に、ブローカーは名前付きメッセージ・ツリーをナビゲートして、変更する必要のあるメッセージ・ツリー内のポイントを見つける必要があります。 以下に例を示します。

  • フィールド 1 にアクセスするために SET ステートメントは ParentA までナビゲートした後、最初のフィールドまでナビゲートします。こうして 2 回のナビゲーションが発生します。
  • フィールド 5 にアクセスするために SET ステートメントは ParentA までナビゲートした後、その前の各フィールドを全探索してフィールド 5 に到達します。こうして 6 回のナビゲーションが発生します。

指定されたフィールドに先行するすべてのフィールドをナビゲートすることは、パフォーマンス低下の原因になります。

以下に示す例では、反復するフィールドが入力メッセージ・ツリー内でアクセスされます。
DECLARE myChar CHAR;
DECLARE thisRecord INT 0;
WHILE thisRecord < 10000 DO
	SET thisRecord = thisRecord + 1;
	SET myChar = InputRoot.MRM.myParent.myRepeatingRecord[thisRecord];
END WHILE;  
索引表記を使用した場合、カウントが増加するにつれて、この処理では必要なフィールドに到達するまでに、先行するすべてのフィールドをナビゲートする必要が生じます。つまり、現行の索引参照によって表されているレコードに到達するために、それ以前のレコードをカウントする必要があります。
  • InputRoot.MRM.myParent.myRepeatingRecord[1] にアクセスする際、最初のレコードに到達するために 1 回のナビゲーションが行われます。
  • InputRoot.MRM.myParent.myRepeatingRecord[2] にアクセスする際、2 番目のレコードに到達するために 2 回のナビゲーションが行われます。
  • InputRoot.MRM.myParent.myRepeatingRecord[N] にアクセスする際、N 番目のレコードに到達するために N 回のナビゲーションが行われます。

したがって、この WHILE ループのナビゲーションの合計数は、1 + 2 + 3 + .... + N 回になります。これは線形ではありません。

連続する複数のフィールドやレコードにアクセスしたり、それらを作成したりする場合は、参照変数を使ってこの問題を解決できます。

参照変数を使用した場合、ステートメントはメッセージ・ツリー内のフィールドへのポインターが維持されているメインの親にナビゲートします。 次の例では、新規出力メッセージ・ツリー・フィールドを作成する場合に、ナビゲーションの数を削減するために使用できる ESQL を示します。

SET OutputRoot.XMLNS.TestCase.StructureA.ParentA.field1 = '1';
DECLARE outRef REFERENCE TO OutputRoot.XMLNS.TestCase.StructureA.ParentA;
SET outRef.field2 = '2';
SET outRef.field3 = '3';
SET outRef.field4 = '4';
SET outRef.field5 = '5';

反復される入力メッセージ・ツリー・フィールドを参照する場合、次の ESQL を使用できます。

DECLARE myChar CHAR;
DECLARE inputRef REFERENCE TO InputRoot.MRM.myParent.myRepeatingRecord[1];
WHILE LASTMOVE(inputRef) DO
	SET myChar = inputRef;
	MOVE inputRef NEXTSIBLING NAME 'myRepeatingRecord';
END WHILE;

詳細については、動的フィールド参照の作成を参照してください。

特記事項 | 商標 | ダウンロード | ライブラリー | サポート | フィードバック

Copyright IBM Corporation 1999, 2014Copyright IBM Corporation 1999, 2014.

        
        最終更新:
        
        最終更新: 2015-02-28 17:49:14


タスク・トピックタスク・トピック | バージョン 8.0.0.5 | bj28653_