Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005
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:
- Page 288 and 289: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 290 and 291: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 292 and 293: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 294 and 295: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 296 and 297: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 298 and 299: CHAPTER 7 ■ CONCURRENCY AND MULTI
- Page 300 and 301: CHAPTER 8 ■ ■ ■ Transactions
- Page 302 and 303: CHAPTER 8 ■ TRANSACTIONS 257 •
- Page 304 and 305: CHAPTER 8 ■ TRANSACTIONS 259 So,
- Page 306 and 307: CHAPTER 8 ■ TRANSACTIONS 261 X --
- Page 308 and 309: CHAPTER 8 ■ TRANSACTIONS 263 “s
- Page 310 and 311: CHAPTER 8 ■ TRANSACTIONS 265 busi
- Page 312 and 313: CHAPTER 8 ■ TRANSACTIONS 267 Many
- Page 314 and 315: CHAPTER 8 ■ TRANSACTIONS 269 ops$
- Page 316 and 317: CHAPTER 8 ■ TRANSACTIONS 271 last
- Page 318 and 319: CHAPTER 8 ■ TRANSACTIONS 273 Dist
- Page 320 and 321: CHAPTER 8 ■ TRANSACTIONS 275 Auto
- Page 322 and 323: CHAPTER 8 ■ TRANSACTIONS 277 3 Au
- Page 324 and 325: CHAPTER 8 ■ TRANSACTIONS 279 5 pr
- Page 326: CHAPTER 8 ■ TRANSACTIONS 281 scot
- Page 329 and 330: 284 CHAPTER 9 ■ REDO AND UNDO cri
- Page 331 and 332: 286 CHAPTER 9 ■ REDO AND UNDO Fir
- Page 333 and 334: 288 CHAPTER 9 ■ REDO AND UNDO The
- Page 335 and 336: 290 CHAPTER 9 ■ REDO AND UNDO We
- Page 337: 292 CHAPTER 9 ■ REDO AND UNDO Wha
- Page 341 and 342: 296 CHAPTER 9 ■ REDO AND UNDO If
- Page 343 and 344: 298 CHAPTER 9 ■ REDO AND UNDO ops
- Page 345 and 346: 300 CHAPTER 9 ■ REDO AND UNDO Inv
- Page 347 and 348: 302 CHAPTER 9 ■ REDO AND UNDO The
- Page 349 and 350: 304 CHAPTER 9 ■ REDO AND UNDO 41
- Page 351 and 352: 306 CHAPTER 9 ■ REDO AND UNDO ins
- Page 353 and 354: 308 CHAPTER 9 ■ REDO AND UNDO So,
- Page 355 and 356: 310 CHAPTER 9 ■ REDO AND UNDO ops
- Page 357 and 358: 312 CHAPTER 9 ■ REDO AND UNDO ops
- Page 359 and 360: 314 CHAPTER 9 ■ REDO AND UNDO •
- Page 361 and 362: 316 CHAPTER 9 ■ REDO AND UNDO ...
- Page 363 and 364: 318 CHAPTER 9 ■ REDO AND UNDO •
- Page 365 and 366: 320 CHAPTER 9 ■ REDO AND UNDO bac
- Page 367 and 368: 322 CHAPTER 9 ■ REDO AND UNDO As
- Page 369 and 370: 324 CHAPTER 9 ■ REDO AND UNDO ops
- Page 371 and 372: 326 CHAPTER 9 ■ REDO AND UNDO wil
- Page 373 and 374: 328 CHAPTER 9 ■ REDO AND UNDO Thi
- Page 375 and 376: 330 CHAPTER 9 ■ REDO AND UNDO ops
- Page 377 and 378: 332 CHAPTER 9 ■ REDO AND UNDO Whe
- Page 379 and 380: 334 CHAPTER 9 ■ REDO AND UNDO Tha
- Page 381 and 382: 336 CHAPTER 9 ■ REDO AND UNDO tou
- Page 383 and 384: 338 CHAPTER 10 ■ DATABASE TABLES
- Page 385 and 386: 340 CHAPTER 10 ■ DATABASE TABLES
- Page 387 and 388: 342 CHAPTER 10 ■ DATABASE TABLES
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: