Skip to Main Content
  • Questions
  • Recommendations for JAVA executing SQL

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Matt.

Asked: September 27, 2003 - 10:25 pm UTC

Last updated: November 21, 2003 - 3:39 pm UTC

Version: 9.0.1

Viewed 1000+ times

You Asked

I have been looking for some good Java coding standards to be used when using Java with an Oracle database. Specifically some 'best practices' for Java running SQL against Oracle. I have very little Java exposure, but I think that I am looking for an understanding of when to use the following constructs:

Statement (<- never, since cannot use bind variables)
PreparedStatement
CallableStatement

I would like to understand when it is most efficient to:

open cursors
close cursors

Additionally, any issues surrounding connections to the database, such as:

Connection Pooling

Finally:

I am looking at enhancing an existing J2EE application. I would like also like to understand where PL/SQL might fit into this standard (if at all).

Are ther eany other considerations when trying to build an efficient Java application using the Oracle RDBMS?

How does the Java package oracle.sql.* fit into all of this?

I appreciate that this might be a bit of a large topic. So, if you can focus on the SQL issues (open, parse, execute, fetch, close) and reference the Oracle docuementation where possible. I have been reading the "Oracle9i JDBC Developer’s Guide and Reference", but have not found any "For performance, consider using these approaches in these situations" type sections.

Can you recommend and "accurate" books on Java development with Oracle? Having read this forum, I am well aware that there are some books out there on this topic that are misleading, if not just incorrect.

Thanks in advance,

Best Regards,

Mat.

and Tom said...

Java is just a language.

Java is just a language.

Java is not any different than C, VB, perl, etc -- it is JUST a language.

I would say my new book "Effective Oracle By Design" is what you are looking for, or "Expert one on one Oracle", or Jonathan Lewis's Practical Oracle8i, or Cary Millsap's Optimizing Oracle Performance.

These are books about how to build good database base applications -- regardless of language.

Java is JUST a 3gl programming language, nothing more, nothing less. The questions you are asking about -- parsing, cursors, stored procedures -- are language independent.

For performance, consider outlawing "select, insert, update, delete, merge, create" in all <any 3gl language goes here> and only permitting such statments in stored procedures. The best 3gl has nothing more then "begin/end" blocks in it (and uses bind variables to invoke those!)

It'll be more performant

It'll be more portable (seems counter intuitive but since the major diffs between databases is NOT our sql syntax but our very core concurrency and integrity models -- this is true)

It'll be easier to tune

It'll be easier to manage

probably not the answer you wanted but -- remember -- java is just a language, just a language.

Rating

  (8 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

My $0.02 on Matt's questions

Peter Tran, September 28, 2003 - 1:14 pm UTC

Matt,

Tom is right...

Here's my experience with JDBC and some rambling thrown in.

1) If you can afford it, buy all the above books. I have them all and they're excellent.
2) Search this site for the word "Menon". He's shared a lot of JAVA code w.r.t. performance. There's also a discussion regarding connection pooling and the ability to reuse SQL statements. Connection pooling makes it harder, but not impossible.

Do not buy any JDBC specific books. They're a waste of money and time. In fact, one of them </code> http://www.oreilly.com/catalog/jorajdbc/
gives the wrong information regarding performance.  Oreilly books are usually very good, but the two they have on JDBC are pretty bad.  I hestitate to even give this link:
http://www.onjava.com/pub/a/onjava/2001/12/19/oraclejdbc.html <code>
but #3 is an example of just WRONG information. This author must have done all his testing on a single CPU Oracle box using one connection to the database. Arghhh....

We had the unfortunate experience of following his advice on a multi-threaded application hitting a 12 processors Oracle box, and needless to say we got hammered. Almost 90% of Oracle's time was spent thrashing the shared pooled reparsing each unique SQL, because we read that Statement performed better.

It took a while to convert the application to use PreparedStatement. Better yet, go with Tom's advice and do it on the database side.

Finally, whatever you do benchmark your JAVA application with real volume in a multi-threaded environment. A small dataset is good to test functionality, but doesn't tell you squat about how your application will scale. I'm learning that we pay to huge price when delay scalabiility testing and we end up letting the clients do it.

HTH,
-Peter

I think that I am with you guys on this one.

Matt, September 28, 2003 - 6:48 pm UTC

I think that I am with you guys on this one.

I'm about 2/3 of the way through "Effective Oracle By Design", I have "Expert one on one Oracle", and Cary Millsap's Optimizing Oracle Performance is in transit from Amazon, (and I've read Steve Adams and James Morle and ..... and thay (the books)are on my bookshelf).

I have also trawled this site to cover what I think comprises the following receommendations from Tom:

* open cursors in your constructors
* close your cursors in your destructors
* ONLY USE BINDS - PreparedStatement or CallableStatement objects
* Don't call SQL directly, wrap your insert, select, update, delet, merge in PL/SQL. This will allow you to take advantage of some of teh performance smarts in PL/SQL as well as know exactly where to find all your SQL for tuning - when you have found it, fix it, recompile your package and your change is implemented simply without any 'major' application re-builds.

Finally, bear in mind that there are no rules of thumb - all 'rules' *may* be broken/ bent/ disregarded in particular circumstances.

This existing application currently uses the Statement construct and therefore no binds. The application itself processes file data that arrive from users. The application processes all of these whilst connected to the DB as a single user. At the moment then, my understanding is that this application is effectively a single user system. It is an interesting conversation to try and convince a change of development approach in this environment - even when you take the best practice argument. ie: When it is easier to write efficient code, why continue with the existing inefficient methods.

I expect that the app is running in hardware that is much meatier that it needs to be.

I'm intersted to hear any other comments regarding J2EE development on Oracle.

Oh, and a decent book reference, of the same calibre as those listed at the beginning of this review would be nice!

Regards all,

Mat.

Tom Kyte
September 28, 2003 - 7:59 pm UTC

you cannot rely on destructors in java, only in Ada can you rely on them....

Cary's book is awesome, i only just got it and I'm on page 100. I'm really enjoying it.

Even in single user mode, they are spending MORE TIME PARSING (probably between 3-5 times) then they are spending actually executing the sql!!!

Only page 100!

Matt, September 28, 2003 - 8:09 pm UTC

So I assume then, that if I am not going down the PL/SQL path, that Java woudl close the cursor explicitly when the cursor has been re-used and DB processing has completed for the particular "object".

Looking forward to Cary's book too. I have just been bitten, by yours though. It's amazing how quickly one can plough through a well written technical book, if it is well written.

I agree - more time parsing and more CPU used than necessary. Less CPU time to do productive work.

In a STATSPACK I expect that I would be seeing lots of hard parses and a high parse/cpu ratio. Any others that I can look out for?

I don't suppose Cary comes up with a way for me to be able to say "Hey, Change this and we will see this measurable benefit".

Thanks again.


Tom Kyte
September 29, 2003 - 7:12 am UTC


java would close the cursor when it was absolutely 100% done with it in that session/ connection....


statpack would show a low or even negative execute to parse ratio.

Cary's book isn't going to give you that nugget, it is going to give you something better -- a methodology, a repeatable one, that can be applied all over the way. so, in a way -- maybe it does in hindsight.

A pure Java approach

Peter Tran, September 29, 2003 - 3:11 am UTC

Matt,

With a pure JAVA approach, you have to do a lot more work. Use connection pooling because opening and closing connections to the database are expensive. Connection pooling makes reusing PreparedStatement more of a challenge, but not impossible. You have to always explicitly close your connection or you'll end up with cursor leaks. The performance won't be as great as having it in the database.

The only argument I've seen put forth for doing it in all JAVA is that it's easier to port the application to a different database (highly arguable). I think this argument is put forth by people (application developers) who are intimidated with database development. Ask a person who's comfortable and knowledgeable about database development (like Tom Kyte), and he'll say do it the database. Ask a person who's done all Java, and he would say do it in Java. Unlike the JAVA guy, Tom gives very convincing arguments for why you should be doing it in the database.

Here's an example statspack of an OLTP multi-threaded application using way too many statements.

DB Name DB Id Instance Inst Num Release Cluster Host
------------ ----------- ------------ -------- ----------- ------- ------------
1 9.2.0.3.0 NO

Snap Id Snap Time Sessions Curs/Sess Comment
------- ------------------ -------- --------- -------------------
Begin Snap: 21 27-Sep-03 00:57:19 307 .3
End Snap: 22 27-Sep-03 01:20:04 304 .3
Elapsed: 22.75 (mins)

Cache Sizes (end)
~~~~~~~~~~~~~~~~~
Buffer Cache: 10,240M Std Block Size: 16K
Shared Pool Size: 304M Log Buffer: 1,024K

Load Profile
~~~~~~~~~~~~ Per Second Per Transaction
--------------- ---------------
Redo size: 265,769.56 92,828.93
Logical reads: 26,635.20 9,303.24
Block changes: 1,996.81 697.45
Physical reads: 49.65 17.34
Physical writes: 20.66 7.21
User calls: 1,508.87 527.02
Parses: 282.46 98.66
Hard parses: 19.60 6.85
Sorts: 215.00 75.10
Logons: 0.02 0.01
Executes: 409.13 142.90
Transactions: 2.86

% Blocks changed per Read: 7.50 Recursive Call %: 18.56
Rollback per transaction %: 0.00 Rows per Sort: 0.81

Instance Efficiency Percentages (Target 100%)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Buffer Nowait %: 100.00 Redo NoWait %: 100.00
Buffer Hit %: 99.82 In-memory Sort %: 100.00
Library Hit %: 94.67 Soft Parse %: 93.06
Execute to Parse %: 30.96 Latch Hit %: 99.87
Parse CPU to Parse Elapsd %: % Non-Parse CPU:

Shared Pool Statistics Begin End
------ ------
Memory Usage %: 90.74 94.71
% SQL with executions>1: 55.27 60.22
% Memory for SQL w/exec>1: 48.75 47.99

Top 5 Timed Events
~~~~~~~~~~~~~~~~~~ % Total
Event Waits Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
latch free 164,859 6,038 85.81
db file sequential read 64,529 812 11.54
db file parallel write 1,859 67 .95
log file sync 3,878 63 .90
log file parallel write 4,153 29 .41
-------------------------------------------------------------

A couple of things I can point out. If you've read Tom's OOO Expert, you'll notice that the Hard Parse and Parse counts are through the roof. My top wait is "latch free" of which I'm spending 85.6% of my time doing. Yep...I would say we have a reparshing too many SQL statements issue. We did have cursor_sharing=force on this database, and it helped a lot. Unfortunately, due to an Oracle bug which crashes the database we had to set the cursor_sharing=exact until the bug is fixed.

-Peter

Would this be a reason to user a Statement?

Matt, September 29, 2003 - 10:38 am UTC

Would the following be e reason to replace Prepared Stements with Statements and concatenated strings parsed into SQL?

"Use connection pooling because opening and closing connections to the database are expensive. Connection pooling makes reusing PreparedStatement more of a challenge, but not impossible. You have to always explicitly close your connection or you'll end up with cursor leaks. The performance won't be as great as having it in the database. "

I'm told that something like this happened on this system. What is the work around - there must have been an easier solution?

Tom Kyte
September 29, 2003 - 12:47 pm UTC

you use prepared statements in order to BIND

if you do not BIND, you die, crash and burn. game over player 1.


you can use prepared statements further to avoid over parsing, but that is incidental.

USE PREPARED STATEMENTS no matter what, even if you just

parse
bind
execute
close


optimally you would

parse once

bind + execute over and over

close




I think you misunderstand me.

Matt, September 29, 2003 - 1:09 pm UTC

I understand and appreciate the need for binds.

The previous poster hinted at a known consideration when using CallableStatements. I beleive that something like this caused the developers of the app I am refering to re-write their binds to use Statements (no binds). I'm told there was some cursor leak.

At the moment this is all rumour. I believe that they must have hit a problem, but that if the re-write was their solution, then it was definately the wrong one.

I would like to understand any "cursor leak" type problems that could be encountered and what I expect would be a relatively simple workaround if I came across this in the future.

Ta,

Cursor leak is not because of using Statement vs PS

Peter Tran, October 03, 2003 - 5:00 pm UTC

Matt,

Cursor leaks is because the developer did not call close on the Statement or PreparedStatement. If you use connection pooling and you call close() on the connection, but you don't explicit close the PreparedStatement or Statement then you'll have a cursor leak. The connection pool doesn't really close the physical connection, so all those unclosed Statements or PreparedStatment will eventually come back and haunt you.

As Tom says,

use Statements
* for DDL.
* in a OLAP application where the SQL is excuted once.

use PreparedStatements every where else.

HTH,
-Peter

Thin JAVA Database Code Layer

Orca777, November 20, 2003 - 3:04 am UTC

if i see JAVA based application running against the database
often there is a configuration like this :

One RAC ( two nodes ) 4G MeM ...
8..16 Application servers ( due to number of seessions )
every 2G MEM ...

I believe if you can use more PL/SQL to reduce Network, and JAVA session memory the number of Application Server could shrink.

But when all SQL is executed by JAVA directly, you need huge resources to to this.

A problem is not solved with object mapping tools like TopLink, i think PL/SQL Usage is not possible.

When i (small)talk with JAVE Experts they do not like to put their attention on database stuff. So the modelling part is perfect, but the perfoamnce part and resources part is under water.

So i am not an enemy of JAVA but if performance is the point you need look over the JAVA universum.

Orca


Tom Kyte
November 21, 2003 - 3:39 pm UTC

(if you use plsql, you do not need toplink -- think about that. they could be considered mutually exclusive)

who cares of the form is beautiful if the function stinks.

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library