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;
参照変数を使用することで、処理時間を大幅に減らすことができます。
WHILE ( I < CARDINALITY (InputRoot.MRM.A.B.C[]
SET ARRAY_SIZE = CARDINALITY (InputRoot.MRM.A.B.C[]
WHILE ( I < ARRAY_SIZE )
1 つのステートメントの中で変数を宣言して初期値を設定することにより、DECLARE ステートメントの数 (およびパフォーマンス・コスト) を減らすことができます。 あるいは、複数のステートメントではなく 1 つの ESQL ステートメントの中で同じデータ型の複数の変数を宣言することもできます。 この手法はメモリー使用量を削減するうえでも役立ちます。
相関名を動的に決定する必要がある場合には、EVAL ステートメントが使われることがあります。 ただしステートメントが 2 回実行されるため、CPU 使用量の点では高コストです。 最初の実行では、実行予定のステートメントを作成するためにコンポーネントの各部が決定されます。その後、作成されたステートメントが実行されます。
PASSTHRU ステートメントを使用する場合、以下の手法によってパフォーマンスが大きく改善される可能性があります。
例えば、以下のステートメントにはデータ値とリテラル値が 2 つあります (100 および IBM)。
PASSTHRU(’UPDATE SHAREPRICES AS SP SET Price = 100 WHERE SP.COMPANY = ‘IBM’’);
このステートメントは、価格が 100 で会社が IBM である場合には効率的です。 Price または Company のどちらかが変更になった場合、別のステートメント (および別の SQL PREPARE ステートメント) が必要になり、パフォーマンスが影響を受けます。
PASSTHRU(’UPDATE SHAREPRICES AS SP SET Price = ? WHERE SP.COMPANY = ?’,
InputRoot.XML.Message.Price,InputRoot.XML.Message.Company);
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>
DECLARE refPtr REFERENCE to InputRoot.XMLNSC.A.B.C.D;
メッセージ・ツリーのエレメント E にアクセスするには、相関名 refPtr.E を使用します。
REFERENCE ステートメントおよび MOVE ステートメントを使用するとメッセージ・ツリー内のナビゲーションの量を減らすことができ、パフォーマンスが改善されます。 この手法は、多数の SET ステートメントまたは CREATE ステートメントを構築する場合に役立つ可能性があります。ツリー内の同じブランチまでナビゲートする代わりに、REFERENCE 変数を使ってブランチへのポインターを設定した後、MOVE ステートメントを使って一度に 1 つのフィールドを処理できます。
ESQL 内で使われるストリング処理関数は CPU を集中的に使用する可能性があります。LENGTH、SUBSTRING、RTRIM などの関数はメッセージ・ツリー内の個々のバイトにアクセスする必要があります。 これらの関数はパフォーマンスの点で高コストであるため、その使用を最小限に抑えるとパフォーマンス改善に役立つ可能性があります。 また、可能であれば、中間結果を変数に保管することで、同じ連結を繰り返し実行することを避けてください。
以下の状況ではパフォーマンスが低下する可能性があります。
この問題は、連続するフィールドまたはレコードのアクセスまたは作成を行うために、参照変数ではなくフィールド参照を使用した場合に発生します。
以下の例に示す独立した 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 の子です。 指定したフィールドを作成または変更する前に、ブローカーは名前付きメッセージ・ツリーをナビゲートして、変更する必要のあるメッセージ・ツリー内のポイントを見つける必要があります。 以下に例を示します。
指定されたフィールドに先行するすべてのフィールドをナビゲートすることは、パフォーマンス低下の原因になります。
DECLARE myChar CHAR;
DECLARE thisRecord INT 0;
WHILE thisRecord < 10000 DO
SET thisRecord = thisRecord + 1;
SET myChar = InputRoot.MRM.myParent.myRepeatingRecord[thisRecord];
END WHILE;
索引表記を使用した場合、カウントが増加するにつれて、この処理では必要なフィールドに到達するまでに、先行するすべてのフィールドをナビゲートする必要が生じます。つまり、現行の索引参照によって表されているレコードに到達するために、それ以前のレコードをカウントする必要があります。したがって、この 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;
詳細については、動的フィールド参照の作成を参照してください。