この章では、TimesTenデータ・ストア上で最適に実行されるようにJavaアプリケーションをチューニングする方法のヒントを示します。 より一般的なチューニングのヒントについては、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』のTimesTen Databaseのパフォーマンス・チューニングに関する項を参照してください。
この章は、次の内容で構成されています。
この項では、TimesTen用のJavaアプリケーションをチューニングする場合の一般的な方針について説明します。内容は次のとおりです。
TimesTen ObservableConnectionDS
クラスによって、準備された文のプールされた接続へのプール(JDBC 3.0の仕様を参照)がサポートされます。 これは、TimesTenのConnectionPoolDataSource
の実装です。 一度有効化すると、文のプールはアプリケーションに対して透過的になることに注意してください。PreparedStatement
オブジェクトの使用(文の準備およびクローズを含む)に違いはありません。
準備された文のプールを有効化して、ObservableConnectionDS
メソッドsetMaxStatements()
をコールすることでプールの文の最大数を指定できます。 デフォルトの値は0で、準備された文プールを無効化しています。 0より大きい任意の整数値を指定すると、その値を文の最大数として、準備された文のプールを有効化します。 設定した後、この値は変更しないでください。
重要: 準備された文のプールを使用する場合、JDBCは、SQLが(コメントを含めて)同一であれば、オプティマイザ設定などの他の考慮事項に関係なく、その2つの文を同一とみなします。 他の点では同一の文に、異なるオプティマイザ・ヒントが適用される可能性がある場合、準備された文のプールは使用しないでください。 使用すると、文の実行により、プールの同一の文が予期しないオプティマイザ設定で使用されることがあります。 |
文の実行グループ(バッチとも呼ばれる)を使用してStatement
またはPreparedStatement
オブジェクトにaddBatch()
およびexecuteBatch()
メソッドをコールすることで、パフォーマンスを向上させることができます。
Statement
オブジェクトの場合、バッチは、通常、一連のINSERT文またはUPDATE文で構成されています。結果セットを返す文は、バッチでは使用できません。 addBatch()
メソッドをコールすると、バッチにSQL文が追加されます。 バッチに関連付けられている一連のSQL文は、executeBatch()
メソッドによって実行されます。
PreparedStatement
オブジェクトの場合、1つのバッチは異なる入力パラメータ値を使用して繰返し実行される1つの文で構成されます。 入力値のセットごとに、必要なset
XXX
()
コールを使用した後に、addBatch()
コールを使用して、バッチを作成します。 バッチは、executeBatch()
メソッドを介して実行されます。
リリース11.2.1では、次のバッチ・サイズをお薦めします。
INSERT文に256
UPDATE文に31
DELETE文に31
例5-1 文へのバッチ
// turn off autocommit conn.setAutoCommit(false); Statement stmt = conn.createStatement(); stmt.addBatch("INSERT INTO employees VALUES (1000, 'Joe Jones')"); stmt.addBatch("INSERT INTO departments VALUES (260, 'Shoe')"); stmt.addBatch("INSERT INTO emp_dept VALUES (1000, 260)"); // submit a batch of update commands for execution int[] updateCounts = stmt.executeBatch(); conn.commit ();
例5-2 準備された文へのバッチ
// turn off autocommit conn.setAutoCommit(false); // prepare the statement PreparedStatement stmt = conn.prepareStatement ("INSERT INTO employees VALUES (?, ?)"); // first set of parameters stmt.setInt(1, 2000); stmt.setString(2, "Kelly Kaufmann"); stmt.addBatch(); // second set of parameters stmt.setInt(1, 3000); stmt.setString(2, "Bill Barnes"); stmt.addBatch(); // submit the batch for execution. Check update counts int[] updateCounts = stmt.executeBatch(); conn.commit ();
Statement
またはPreparedStatement
オブジェクトでは、executeBatch()
メソッドは更新回数の配列(例5-1および例5-2のupdateCounts[]
)と各文の実行の配列の1要素を返します。 各要素の値は次のいずれかになります。
数字は、対応する文の実行によってデータベース内で影響を受ける行の数を示します。
SUCCESS_NO_INFOは、対応する文の実行に成功したことを示しますが、影響を受けた行数については不明です。
EXECUTE_FAILEDは、対応する文の実行に失敗したことを示します。
文の実行がEXECUTE_FAILEDのステータスになると、それ以降、文の実行は試行されません。
JDBCバッチ更新機能の使用方法の詳細は、次の場所にある、Java Platform API仕様のStatement
インタフェースの、executeBatch()
メソッドに関する情報を参照してください。
TimesTenで提供されている拡張を使用すると、アプリケーションで複数のデータ行をフェッチできます。大量のTimesTenデータを取得するアプリケーションの場合、複数行のフェッチによってパフォーマンスを大幅に向上させることができます。ただし、コミット読取り分離モードが使用される場合は、アプリケーションですべてのデータが取得されるまで、取得されるすべての行にロックが設定されるため、同時実行性は低下します。 この機能の詳細は、「複数のデータ行のフェッチ」を参照してください。
Javaの文字列は不変的であるため、ResultSet
メソッドgetString()
は、(基礎となるC文字列からUnicode文字列への変換に加えて、)コールされるたびに新しい文字列用の領域を確保する必要があります。 これは、JDBCにおいて最もコストのかかる処理の1つといえます。
また、必要時以外は、byte
やint
などの基本的な数値型でgetString()
をコールしないでください。 たとえば、整数列の場合、getInt()
をコールする方が大幅に高速に処理が実行されます。
TimesTenの命令パスは非常に短いため、データ変換による短時間の遅延によっても、トランザクション時間が大幅に増加する可能性があります。
基礎となるデータベース内のデータのデータ型に対してのResultSet
オブジェクトには、適切なget
XXX
()
メソッドを使用します。 たとえば、データのデータ型がDOUBLEである場合、JDBCドライバでのデータ変換を避けるために、getDouble()
をコールする必要があります。 同様に、SQL文の入力パラメータには、PreparedStatement
オブジェクトで、適切なset
XXX
()
メソッドを使用します。 たとえば、PreparedStatement
を使用してCHAR列にデータを挿入する場合は、setString()
を使用する必要があります。
この項では、JMS/XLA APIを使用するアプリケーションに固有のパフォーマンス・チューニングのヒントを示します。JMS/XLAでは、オーバーヘッドが発生するため、C XLA APIを使用した場合より低速となります。C APIでは、レコードがユーザーにバッチで戻されます。 JMSモデルでは、オブジェクトがインスタンス化され、MessageListener
メソッドonMessage()
に対するコールバックで各レコードが1つずつ示されます。高パフォーマンスのアプリケーションでは、チューニングを行ってこのオーバーヘッドの一部を回避できます。
この項の内容は次のとおりです。
トランザクション・ログを読み取るJMSレイヤーの基礎となるコードは、オブジェクト/行をユーザーに示す前にできるかぎり多くの行をフェッチ可能な場合、より効率的になります。 プリフェッチの量は、xlaPrefetch
パラメータが指定されたjmsxla.xml
構成ファイルで制御されます。プリフェッチ数は、100、1000などの大きい値に設定します。
C XLAファンクションttXlaAcknowledge
をコールすると、ブックマークが移動され、システム表への更新が実行されます。このため、スループットを増加させる1つの方法として、いくつかのトランザクションが実行されるまで待機してからコールを発行する方法があります。これには、リーダー・アプリケーションで同じレコード・セットが複数回戻されることを許容できる必要があります。 ブックマークの移動は、セッションのインスタンス化の際に、Session
のCLIENT_ACKNOWLEDGEモードを使用して手動で実行できます。
Session session = connection.createSession (false, Session.CLIENT_ACKNOWLEDGE);
この値の妥当な設定値は、ほとんどのアプリケーションの場合、100です。
このファンクションの詳細は、『Oracle TimesTen In-Memory Database C開発者ガイド』のttXlaAcknowledgeに関する項を参照してください。
同期インタフェースは、イベント率が低いアプリケーションと、AUTO_ACKNOWLEDGEまたはDUPS_OK_ACKNOWLEDGE応答モードを許容できるアプリケーションにのみ適しています。 CLIENT_ACKNOWLEDGE応答モードを必要とするアプリケーションと、イベント率が高いアプリケーションでは、更新を受信するために非同期インタフェースを使用する必要があります。 それらのアプリケーションで応答モードとしてCLIENT_ACKNOWLEDGEMENTを使用する場合は、コールバック・スレッド自体のメッセージを確認する必要があります。 「更新の受信および処理」を参照してください。