Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

rekharaghuram
from rekharaghuram More from this publisher
05.11.2015 Views

CHAPTER 9 ■ REDO AND UNDO 293 import java.sql.*; import oracle.jdbc.OracleDriver; import java.util.Date; public class perftest { public static void main (String arr[]) throws Exception { DriverManager.registerDriver(new oracle.jdbc.OracleDriver()); Connection con = DriverManager.getConnection ("jdbc:oracle:thin:@localhost.localdomain:1521:ora10g", "scott", "tiger"); Integer iters = new Integer(arr[0]); Integer commitCnt = new Integer(arr[1]); con.setAutoCommit(false); doInserts( con, 1, 1 ); doInserts( con, iters.intValue(), commitCnt.intValue() ); doInserts( con, iters.intValue(), iters.intValue() ); con.commit(); con.close(); } Now, the method doInserts() is fairly straightforward. It starts by preparing (parsing) an INSERT statement so we can repeatedly bind/execute it over and over: static void doInserts(Connection con, int count, int commitCount ) throws Exception { PreparedStatement ps = con.prepareStatement ("insert into test " + "(id, code, descr, insert_user, insert_date)" + " values (?,?,?, user, sysdate)"); It then loops over the number of rows to insert, binding and executing the INSERT over and over. Additionally, it is checking a row counter to see if it needs to COMMIT or not inside the loop. Note also that before and after the loop we are retrieving the time, so we can monitor elapsed times and report them: int rowcnt = 0; int committed = 0; long start = new Date().getTime(); for (int i = 0; i < count; i++ ) { ps.setInt(1,i); ps.setString(2,"PS - code" + i); ps.setString(3,"PS - desc" + i); ps.executeUpdate();

294 CHAPTER 9 ■ REDO AND UNDO rowcnt++; if ( rowcnt == commitCount ) { con.commit(); rowcnt = 0; committed++; } } con.commit(); long end = new Date().getTime(); System.out.println ("pstatement " + count + " times in " + (end - start) + " milli seconds committed = "+committed); } } Now we’ll run this code repeatedly with different inputs: $ java perftest 10000 1 pstatement 1 times in 4 milli seconds committed = 1 pstatement 10000 times in 11510 milli seconds committed = 10000 pstatement 10000 times in 2708 milli seconds committed = 1 $ java perftest 10000 10 pstatement 1 times in 4 milli seconds committed = 1 pstatement 10000 times in 3876 milli seconds committed = 1000 pstatement 10000 times in 2703 milli seconds committed = 1 $ java perftest 10000 100 pstatement 1 times in 4 milli seconds committed = 1 pstatement 10000 times in 3105 milli seconds committed = 100 pstatement 10000 times in 2694 milli seconds committed = 1 As you can see, the more often you commit, the longer it takes (your mileage will vary on this). This is just a single-user scenario—with multiple users doing the same work, all committing too frequently, the numbers will go up rapidly. We’ve heard the same story, time and time again, with other similar situations. For example, we’ve seen how not using bind variables and performing hard parses frequently severely reduces concurrency due to library cache contention and excessive CPU utilization. Even when we switch to using bind variables, soft parsing too frequently, caused by closing cursors even though we are going to reuse them shortly, incurs massive overhead. We must perform operations only when we need to—a COMMIT is just another such operation. It is best to size our transactions based on business need, not based on misguided attempts to lessen resource usage on the database. There are two contributing factors to the expense of the COMMIT in this example:

294<br />

CHAPTER 9 ■ REDO AND UNDO<br />

rowcnt++;<br />

if ( rowcnt == commitCount )<br />

{<br />

con.commit();<br />

rowcnt = 0;<br />

committed++;<br />

}<br />

}<br />

con.commit();<br />

long end = new Date().getTime();<br />

System.out.println<br />

("pstatement " + count + " times in " +<br />

(end - start) + " milli seconds committed = "+committed);<br />

}<br />

}<br />

Now we’ll run this code repeatedly with different inputs:<br />

$ java perftest 10000 1<br />

pstatement 1 times in 4 milli seconds committed = 1<br />

pstatement 10000 times in 11510 milli seconds committed = 10000<br />

pstatement 10000 times in 2708 milli seconds committed = 1<br />

$ java perftest 10000 10<br />

pstatement 1 times in 4 milli seconds committed = 1<br />

pstatement 10000 times in 3876 milli seconds committed = 1000<br />

pstatement 10000 times in 2703 milli seconds committed = 1<br />

$ java perftest 10000 100<br />

pstatement 1 times in 4 milli seconds committed = 1<br />

pstatement 10000 times in 3105 milli seconds committed = 100<br />

pstatement 10000 times in 2694 milli seconds committed = 1<br />

As you can see, the more often you commit, the longer it takes (your mileage will vary on<br />

this). This is just a single-user scenario—with multiple users doing the same work, all committing<br />

too frequently, the numbers will go up rapidly.<br />

We’ve heard the same story, time <strong>and</strong> time again, with other similar situations. For example,<br />

we’ve seen how not using bind variables <strong>and</strong> performing hard parses frequently severely<br />

reduces concurrency due to library cache contention <strong>and</strong> excessive CPU utilization. Even<br />

when we switch to using bind variables, soft parsing too frequently, caused by closing cursors<br />

even though we are going to reuse them shortly, incurs massive overhead. We must perform<br />

operations only when we need to—a COMMIT is just another such operation. It is best to size our<br />

transactions based on business need, not based on misguided attempts to lessen resource<br />

usage on the database.<br />

There are two contributing factors to the expense of the COMMIT in this example:

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!