この項では、TimesTenデータ・ストアのデータの処理について説明します。内容は次のとおりです。
この項の内容は次のとおりです。
TimesTen Connectionではデフォルトで自動コミットが有効になっています。Connection.setAutoCommit()を使用すると、自動コミットを有効/無効を切り替えることができます。自動コミットが無効になっている(falseに設定されている)場合は、Connection.commit()を使用して、トランザクションを手動でコミットする必要があります。
たとえば、自動コミットをオフに設定するには次のように入力します。
con.setAutoCommit(false);
// Report any SQLWarnings on the connection
// See "Reporting errors and warnings"
複数回実行するSQL文は、Connection.prepareStatement()メソッドをコールして事前に準備しておく必要があります。
最大のパフォーマンスを得るために、パラメータ化した文を準備します。TimesTenでは、重複したパラメータを含むSQL文は解析されるため、異なる名前のパラメータのみが別のパラメータとして認識されます。バインドは、パラメータ名が最初に出現した位置に基づいて行われます。重複した各パラメータは同じ値にバインドされます。
例2.3に、4つのINSERT文をパラメータ化された1つの文に置き換える方法を示します。
値が異なる同様のINSERT文の実行:
Statement.execute("insert into t1 values (1, 2)");
Statement.execute("insert into t1 values (3, 4)");
Statement.execute("insert into t1 values (5, 6)");
Statement.execute("insert into t1 values (7, 8)");
パラメータ化した1つのINSERT文を準備し、各文を実行する前にPreparedStatement.set...()メソッドを使用して行の値を設定する方がより効率的です。
PreparedStatement pIns =
con.PreparedStatement("insert into t1 values (?,?)");
con.commit();
pIns.setInt(1, Integer.parseInt(1));
pIns.setInt(2, Integer.parseInt(2));
pIns.executeUpdate();
pIns.setInt(1, Integer.parseInt(3));
pIns.setInt(2, Integer.parseInt(4));
pIns.executeUpdate();
pIns.setInt(1, Integer.parseInt(5));
pIns.setInt(2, Integer.parseInt(6));
pIns.executeUpdate();
pIns.setInt(1, Integer.parseInt(7));
pIns.setInt(2, Integer.parseInt(8));
pIns.executeUpdate();
con.commit();
pIns.close();
注意: | SQL文を準備した後、 Connection.commit()をコールして、準備によって適用されたロックを解除し、問合せ計画を保持できるようにしてください。準備された文の実行が完了した後、 PreparedStatement.close()メソッドをコールして、この文に関連付けられているリソースを解放してください。 |
TimesTenでは、準備された文がコミットされると、自動的に共有されます。たとえば、データ・ストアへの複数の接続でそれぞれ同じ文が準備される場合、TimesTenでは、準備された最初の文が記憶されているため、2番目以降の準備が迅速に返されます。
この例では、3つの接続に対してパラメータ化された同じINSERT文を3つ準備します。接続con1 に対して最初に準備するINSERTは、con2 接続およびcon3 接続で共有されるため、pIns2 およびpIns3 の準備操作が高速に行われます。
Connection con1;
Connection con2;
Connection con3;
.....
PreparedStatement pIns1 = con1.prepareStatement
("insert into t1 values (?,?)");
con1.commit();
PreparedStatement pIns2 = con2.prepareStatement
("insert into t1 values (?,?)");
con2.commit();
PreparedStatement pIns3 = con3.prepareStatement
("insert into t1 values (?,?)");
con3.commit();
注意: | 結合順序、索引、ロックなど、すべてのチューニング・オプションが共有される文に適している必要があります。また、準備された文が一時表を参照する場合、この文は1つの接続内でのみ共有されます。 |
注意: | TimesTenでは、JDBC 3.0仕様で指定されているように、 PooledConnection用に準備された文のプールもサポートされています。最大サイズのプールを構成するには、ObservableConnectionDS.setMaxStatements()を設定します。設定した後、この値は変更しないでください。 |
事前にSQL文を準備することによるパフォーマンス上の利点については、「文の事前準備」を参照してください。
SQLを使用してTimesTenデータ・ストアのデータを管理する方法については、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』のTimesTenデータ・ストアのデータの処理に関する章を参照してください。この項では、 Connection.createStatement()メソッド、 Statement.executeUpdate()メソッドおよびStatement.executeQuery()メソッドを使用して、Javaアプリケーション内でSQL文を実行する方法について説明します。
「SQL文の準備」で説明したとおり事前に文が準備されていない場合は、SQL文の特性および返された結果セットに応じて、Statement.execute()、Statement.executeUpdate()、Statement.executeQuery()などのStatement実行メソッドを使用します。
事前に準備されたSQL文には、PreparedStatement.execute()、PreparedStatement.executeUpdate()、PreparedStatement.executeQuery()などのPreparedStatement実行メソッドを使用します。
execute()メソッドは、結果セットがある場合はTrueを返し(SELECTなど)、結果セットがない場合はFalseを返します(INSERT、UPDATE、DELETEなど)。executeUpdate()メソッドは、影響を受ける行数を返します。たとえば、INSERT文を実行すると、executeUpdate()メソッドは挿入された行数を返します。executeQuery()メソッドは結果セットを返すため、結果セットが必要な場合(SELECTの実行時など)にのみコールする必要があります。
注意: | TimesTenで生成された結果セットの使用に関する注意事項は、「結果セットの使用」を参照してください。 |
Statement.executeUpdate() メソッドを使用して、xyz.customer 表へのINSERTを実行するには、次のように入力します。
Connection con;
Statement stmt;
. . . . . .
try {
stmt = con.createStatement();
int numRows = stmt.executeUpdate("insert into xyz.customer
values" + "(40, 'West', 'Big Dish', '123 Signal St.');");
}
catch (SQLException ex) {
.....
}
この例では、Statement.executeQuery() メソッドを使用して、xyz.customer 表に対してSELECTを実行し、返された ResultSetを表示します。
Statement stmt;
. . . . . .
try {
ResultSet rs = stmt.executeQuery("select cust_num, region, " +
"name, address from xyz.customer;");
System.out.println("Fetching result set...");
while (rs.next()) {
System.out.println("\n Customer number: " + rs.getInt(1));
System.out.println(" Region: " + rs.getString(2));
System.out.println(" Name: " + rs.getString(3));
System.out.println(" Address: " + rs.getString(4));
}
}
catch (SQLException ex) {
ex.printStackTrace();
}
この例では、PreparedStatement.executeQuery()メソッドを使用して、準備済のSELECT文を実行し、返されたResultSetを表示します。
PreparedStatement pSel = con.prepareStatement("select cust_num, " +
"region, name, address " +
"from xyz.customer;");
con.commit();
try {
ResultSet rs = pSel.executeQuery();
while (rs.next()) {
System.out.println("\n Customer number: " + rs.getInt(1));
System.out.println(" Region: " + rs.getString(2));
System.out.println(" Name: " + rs.getString(3));
System.out.println(" Address: " + rs.getString(4));
}
}
catch (SQLException ex) {
ex.printStackTrace();
}
TimesTenでは、DSN属性SqlQueryTimeoutを設定して、すべての接続に対して問合せのタイムアウト期間を指定できます。DSN仕様にSqlQueryTimeoutを設定すると、その値が、今後のデータ・ストアへのすべての接続のデフォルト値となります。
現行の接続のSqlQueryTimeout値を上書きするには、Statement.setQueryTimeout()メソッドをコールして、データ・ストアでSQL問合せが実行される制限時間(秒)を指定します。TimesTenでは、タイムアウト・トリガーが起動されると、実行中の問合せに対してタイムアウトが指示されます。タイムアウト・メッセージが問合せに達するまでにタイムラグが発生する可能性あるため、問合せが終了するまでの実際の時間は、タイムアウト・メッセージが問合せに達するまでにかかる時間と指定したタイムアウト値を加算した時間になります。
Statement.setQueryTimeout()メソッドは、SQL文がアクティブに実行されている場合にのみ動作します。処理のコミット中またはロールバック中にタイムアウトは発生しません。多数のUPDATE、DELETEまたはINSERTを実行するトランザクションでは、コミットまたはロールバックが完了するまでに時間がかかる場合があります。その間、タイムアウト値は無視されます。
注意: | TimesTenのLockWaitとSqlQueryTimeoutは別々の機能であり、別の値を指定できます。TimesTenは、ロック・タイムアウト値およびSQLQueryTimeout値の両方を確認します。TimesTenは、すべてのスレッドを確認し、ロック・タイムアウトまたはSQL問合せタイムアウトのいずれかが指定されているスリープ中のプロセスのスリープ状態を解除して、実行中のスレッドに適切なSqlQueryTimeout値を指定します。LockWaitタイムアウト値およびSqlQueryTimeout値の両方が指定されている場合は、まず、2つの値の小さい方の値によってタイムアウトが発生します。 |
この例では、INSERT文とSELECT文を準備し、INSERTを2回実行します。また、SELECTを実行し、返された結果セットを印刷します。作業例については、 level1.java
デモを参照してください。
Connection con;
Statement stmt;
// Disable auto-commit
con.setAutoCommit(false);
// Report any SQLWarnings on the connection
// See "Reporting errors and warnings"
// Prepare a parameterized INSERT and a SELECT Statement
PreparedStatement pIns = con.prepareStatement("insert into xyz.customer values (?,?,?,?)");
PreparedStatement pSel = con.prepareStatement
("select cust_num, region, name, " +
"address from xyz.customer");
// Prepare is a transaction; must commit to release locks
con.commit();
// Data for first INSERT statement
pIns.setInt(1, Integer.parseInt(100));
pIns.setString(2, 'N');
pIns.setString(3, 'Fiberifics');
pIns.setString(4,'123 any street');
// Execute the INSERT statement
pIns.executeUpdate();
// Data for second INSERT statement
pIns.setInt(1, Integer.parseInt(101));
pIns.setString(2, 'N');
pIns.setString(3,'Natural Foods Co.');
pIns.setString(4,'5150 Johnson Rd');
// Execute the INSERT statement
pIns.executeUpdate();
// Commit the inserts
con.commit();
// Done with INSERTs, so close the prepared statement
pIns.close();
// Report any SQLWarnings on the connection
reportSQLWarnings(con.getWarnings());
CheckIfStopIsRequested();
// Execute the prepared SELECT statement
ResultSet rs = pSel.executeQuery();
System.out.println("Fetching result set...");
while (rs.next()) {
System.out.println("\n Customer number: " + rs.getInt(1));
System.out.println(" Region: " + rs.getString(2));
System.out.println(" Name: " + rs.getString(3));
System.out.println(" Address: " + rs.getString(4));
}
// Close the result set.
rs.close();
// Commit the select - yes selects need to be committed too
con.commit();
// Close the select statement - we're done with it
pSel.close();
TimesTenデータ・ストアから複数のデータ行をフェッチすると、コミット読取り分離レベルが設定されたデータ・ストアに接続しているアプリケーションのパフォーマンスを向上させることができます。
プリフェッチされる行数を指定するには、次の手順を実行します。
この項では、TimesTenで実装されている接続レベルのプリフェッチについて説明します。
注意: | 直接リンクされたアプリケーションでのみ、TimesTenのプリフェッチ・カウント拡張を使用できます。 |
プリフェッチ数を0(ゼロ)に設定すると、TimesTenは、データ・ストアに設定した分離レベルに応じて、デフォルトの値を使用します。コミット読取り分離モードでは、デフォルトのプリフェッチの値は5です。シリアライズ可能分離モードでは、デフォルトのプリフェッチの値は128です。デフォルトのプリフェッチの値はほとんどのアプリケーションに最適な設定です。一般的に、値を高く設定すると、リソースの使用量がわずかに増加しますが、大きい結果セットに対するパフォーマンスは向上する可能性があります。
プリフェッチを無効にするには、プリフェッチ数を1に設定します。
TimesTenConnection.getTtPrefetchCount()をコールして、現行のプリフェッチ値を確認します。
この例では、ttIsql prefetchcountコマンドを使用して、接続のプリフェッチ数を6に設定します。
> ttIsql RunData_tt51
Command > prefetchcount 6;
この例では、setTtPrefetchCount()を使用して、プリフェッチ数を10に設定し、getTtPrefetchCount()を使用して、カウント変数のプリフェッチ数を返します。
TimesTenConnection con =
(TimesTenConnection) DriverManager.getConnection(url);
// set prefech count to 10 for this connection
con.setTtPrefetchCount(10);
// Return the prefetch count to the 'count' variable.
int count = con.getTtPrefetchCount();
StatementオブジェクトおよびPreparedStatementオブジェクトに対してaddBatch() メソッドおよびexecuteBatch()メソッドをコールすると、パフォーマンスを向上させることができます。
Statementオブジェクトの場合、バッチは、通常、一連のINSERT文またはUPDATE文で構成されています。結果セットを返す文は、バッチでは使用できません。addBatch()メソッドをコールすると、バッチにSQL文が追加されます。バッチに関連付けられている一連のSQL文は、executeBatch()メソッドによって実行されます。次に例を示します。
// 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 ();
PreparedStatementオブジェクトの場合、バッチは一連の準備済の文の入力パラメータで構成されています。準備済の文のパラメータは、set コールの後にaddBatch()コールを実行することによってバッチに追加されます。バッチは、executeBatch()メソッドを介して実行されます。次に例を示します。
// turn off autocommit
conn.setAutoCommit(false);
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 ();
問合せ以外に、一部のメソッドおよび組込みプロシージャでもTimesTenデータがResultSetオブジェクトの形式で返されます。この項では、TimesTenからのResultSetオブジェクトの使用について説明します。